Проверка того, реализует ли класс экземпляра интерфейс?

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

Ответ 1

interface IInterface
{
}

class TheClass implements IInterface
{
}

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

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

Ответ 2

Как указывает therefromhere, вы можете использовать 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);
}

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

Ответ 3

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

Ответ 4

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

if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
    echo 'I can do something !';
}

Ответ 5

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

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

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