Проверка, реализует ли класс экземпляра интерфейс? - PullRequest
137 голосов
/ 08 ноября 2008

Учитывая экземпляр класса, возможно ли определить, реализует ли он определенный интерфейс? Насколько я знаю, нет встроенной функции, чтобы сделать это напрямую. Какие варианты у меня есть (если есть)?

Ответы [ 5 ]

237 голосов
/ 08 ноября 2008
interface IInterface
{
}

class TheClass implements IInterface
{
}

$cls = new TheClass();
if ($cls instanceof IInterface) {
    echo "yes";
}

Вы можете использовать оператор instanceof. Чтобы использовать его, левый операнд является экземпляром класса, а правый операнд является интерфейсом. Возвращает true, если объект реализует определенный интерфейс.

89 голосов
/ 20 августа 2012

Поскольку оттуда указывает, вы можете использовать class_implements(). Как и в Reflection, это позволяет вам указывать имя класса в виде строки и не требует экземпляра класса:

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

Тесты производительности

Некоторые простые тесты производительности показывают стоимость каждого подхода:

С учетом экземпляра объекта

Object construction outside the loop (100,000 iterations)
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 140 ms           | 290 ms     | 35 ms      |
'--------------------------------------------'

Object construction inside the loop (100,000 iterations)
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 182 ms           | 340 ms     | 83 ms      | Cheap Constructor
| 431 ms           | 607 ms     | 338 ms     | Expensive Constructor
'--------------------------------------------'

Дано только имя класса

100,000 iterations
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 149 ms           | 295 ms     | N/A        |
'--------------------------------------------'

Где дорогой __construct ():

public function __construct() {
    $tmp = array(
        'foo' => 'bar',
        'this' => 'that'
    );  

    $in = in_array('those', $tmp);
}

Эти тесты основаны на этом простом коде .

55 голосов
/ 08 ноября 2008

nlaq указывает, что instanceof может использоваться для проверки, является ли объект экземпляром класса, который реализует интерфейс.

Но instanceof не различает тип класса и интерфейс. Вы не знаете, является ли объект классом , который называется IInterface.

Вы также можете использовать API отражения в PHP для более конкретной проверки:

$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
  print "Yep!\n";
}

См. http://php.net/manual/en/book.reflection.php

17 голосов
/ 17 февраля 2014

Просто чтобы помочь будущим поискам is_subclass_of также является хорошим вариантом (для PHP 5.3.7 +):

if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
    echo 'I can do it!';
}
5 голосов
/ 31 августа 2015

Вы также можете сделать следующее

public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
   //.....
}

Будет выдано исправимое сообщение об ошибке, если $objectSupposedToBeImplementing не реализует интерфейс YourInterface.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...