Відповіді:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Можна скористатися оператором "instanceof". Для його використання лівий операнд є екземпляром класу, а правий операнд - інтерфейсом. Він повертає true, якщо об'єкт реалізує певний інтерфейс.
Як звідти вказується, ви можете використовувати class_implements()
. Як і у випадку з відображенням, це дозволяє вказати ім'я класу як рядок і не вимагає примірника класу:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$interfaces = class_implements('TheClass');
if (isset($interfaces['IInterface'])) {
echo "Yes!";
}
class_implements()
є частиною розширення SPL.
Дивіться: http://php.net/manual/en/function.class-implements.php
Деякі прості тести на ефективність показують витрати кожного підходу:
Побудова об'єкта поза циклом (100 000 ітерацій) ____________________________________________ | class_implements | Відбиття | instanceOf | | ------------------ | ------------ | ------------ | | 140 мс | 290 мс | 35 мс | '--------------------------------------------' Побудова об'єкта всередині циклу (100 000 ітерацій) ____________________________________________ | class_implements | Відбиття | instanceOf | | ------------------ | ------------ | ------------ | | 182 мс | 340 мс | 83 мс | Дешевий конструктор | 431 мс | 607 мс | 338 мс | Дорогий конструктор '--------------------------------------------'
100 000 ітерацій ____________________________________________ | class_implements | Відбиття | instanceOf | | ------------------ | ------------ | ------------ | | 149 мс | 295 мс | Н / А | '--------------------------------------------'
Де дорогий __construct ():
public function __construct() {
$tmp = array(
'foo' => 'bar',
'this' => 'that'
);
$in = in_array('those', $tmp);
}
Ці тести засновані на цьому простому коді .
nlaq вказує, що instanceof
можна використовувати для перевірки, чи об'єкт є екземпляром класу, який реалізує інтерфейс.
Але instanceof
не розрізняє тип класу та інтерфейс. Ви не знаєте, чи є об'єктом клас, який, можливо, викликається IInterface
.
Ви також можете використовувати API відбиття в PHP, щоб перевірити це більш конкретно:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
class_implements()
instanceof
знову.
class_implements()
оскільки, очевидно, швидше викликати class_implements, а потім in_array, а не робити повне роздуми
Просто для подальшого пошуку is_subclass_of також є хорошим варіантом (для PHP 5.3.7+):
if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
echo 'I can do it!';
}
Тут is_a
функція відсутня як альтернатива.
Я зробив кілька тестів на ефективність, щоб перевірити, який із зазначених способів є найбільш ефективним.
instanceof [object] took 7.67 ms | + 0% | ..........
is_a [object] took 12.30 ms | + 60% | ................
is_a [class] took 17.43 ms | +127% | ......................
class_implements [object] took 28.37 ms | +270% | ....................................
reflection [class] took 34.17 ms | +346% | ............................................
Додано кілька крапок, щоб насправді "відчути" бачити різницю.
Створено цим: https://3v4l.org/8Cog7
Якщо у вас є об'єкт для перевірки, використовуйте, instance of
як зазначено у прийнятій відповіді.
Якщо у вас є клас для перевірки, використовуйте is_a
.
З огляду на випадок, коли ви хочете інстанціювати клас на основі інтерфейсу, який вам потрібен, він більш складний у використанні is_a
. Є лише один виняток - коли конструктор порожній.
Приклад:
is_a(<className>, <interfaceName>, true);
Це повернеться bool
. Третій параметр " enable_string " дозволяє йому перевіряти назви класів без ініціалізації класу.