





interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Вы можете использовать оператор instanceof. Чтобы использовать его, левый операнд - это экземпляр класса, а правый операнд - это интерфейс. Он возвращает истину, если объект реализует определенный интерфейс.
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
Это можно использовать в "статических" классах.
@therefromhere: Спасибо, хороший совет. Это часть расширения SPL. В моем ответе использовалось расширение Reflection.
Если вы используете пространства имен, тогда не будет неоднозначности между интерфейсами и классами с одинаковыми именами, и вы можете снова безопасно использовать instanceof.
+1 для class_implements(), так как он, очевидно, быстрее вызывает class_implements, а затем in_array, вместо того, чтобы делать полное отражение
Как указывает оттуда, вы можете использовать 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);
}
Эти тесты основаны на этот простой код.
is_subclass_of - также хороший вариант для облегчения будущих поисков (для PHP 5.3.7+):
if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
echo 'I can do it!';
}
Вы также можете сделать следующее
public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
//.....
}
Это вызовет исправляемую ошибку, если $objectSupposedToBeImplementing не реализует интерфейс YourInterface.
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. Третий параметр «allow_string» позволяет ему проверять имена классов без, создающие экземпляр класса.
Обратите внимание, что это не будет полезно, если вы пытаетесь определить конструктор класса.