Учитывая экземпляр класса, возможно ли определить, реализует ли он конкретный интерфейс? Насколько я знаю, нет встроенной функции, чтобы сделать это напрямую. Какие варианты у меня есть (если есть)?
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Вы можете использовать оператор instanceof. Чтобы использовать его, левый операнд является экземпляром класса, а правый операнд является интерфейсом. Возвращает true, если объект реализует определенный интерфейс.
Как оттуда указывает, вы можете использовать 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
Некоторые простые тесты производительности показывают стоимость каждого подхода:
Построение объекта вне цикла (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 мс | N / A | '--------------------------------------------'
Где дорогой __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+):
источник
Вы также можете сделать следующее
Он выдаст исправимую ошибку, если
$objectSupposedToBeImplementing
не реализуетYourInterface
интерфейс.источник
Обновить
is_a
Функция здесь отсутствует как альтернатива.Я провел несколько тестов производительности, чтобы проверить, какой из указанных способов наиболее эффективен.
Результаты более 100 000 итераций
Добавлены некоторые точки, чтобы «почувствовать» разницу.
Генерируется этим: https://3v4l.org/8Cog7
Вывод
Если у вас есть объект для проверки, используйте
instance of
как указано в принятом ответе.Если у вас есть класс для проверки, используйте
is_a
.бонус
Учитывая тот случай, когда вы хотите создать экземпляр класса, основанного на интерфейсе, который вам необходим, он более предпочтителен для использования
is_a
. Есть только одно исключение - когда конструктор пуст.Пример:
is_a(<className>, <interfaceName>, true);
Это вернется
bool
. Третий параметр " allow_string " позволяет ему проверять имена классов без создания экземпляра класса.источник