Dada uma instância de classe, é possível determinar se ela implementa uma interface específica? Até onde eu sei, não há uma função interna para fazer isso diretamente. Que opções eu tenho (se houver)?
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Você pode usar o operador "instanceof". Para usá-lo, o operando esquerdo é uma instância de classe e o operando direito é uma interface. Retorna true se o objeto implementa uma interface específica.
Como a partir daí , você pode usar class_implements()
. Assim como no Reflection, isso permite que você especifique o nome da classe como uma string e não requer uma instância da classe:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$interfaces = class_implements('TheClass');
if (isset($interfaces['IInterface'])) {
echo "Yes!";
}
class_implements()
faz parte da extensão SPL.
Veja: http://php.net/manual/en/function.class-implements.php
Alguns testes simples de desempenho mostram os custos de cada abordagem:
Construção de objetos fora do loop (100.000 iterações) ____________________________________________ | class_implements | Reflexão instanceOf | | ------------------ | ------------ | ------------ | | 140 ms | 290 ms | 35 ms | '--------------------------------------------' Construção de objetos dentro do loop (100.000 iterações) ____________________________________________ | class_implements | Reflexão instanceOf | | ------------------ | ------------ | ------------ | | 182 ms | 340 ms | 83 ms | Construtor Barato | 431 ms | 607 ms | 338 ms | Construtor caro '--------------------------------------------'
100.000 iterações ____________________________________________ | class_implements | Reflexão instanceOf | | ------------------ | ------------ | ------------ | | 149 ms | 295 ms | N / a '--------------------------------------------'
Onde o __construct () caro é:
public function __construct() {
$tmp = array(
'foo' => 'bar',
'this' => 'that'
);
$in = in_array('those', $tmp);
}
Esses testes são baseados neste código simples .
O nlaq aponta que instanceof
pode ser usado para testar se o objeto é uma instância de uma classe que implementa uma interface.
Mas instanceof
não faz distinção entre um tipo de classe e uma interface. Você não sabe se o objeto é uma classe que é chamada IInterface
.
Você também pode usar a API de reflexão no PHP para testar isso mais especificamente:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
class_implements()
instanceof
novamente.class_implements()
desde a sua obviamente mais rápido para chamar class_implements e depois in_array, em vez de fazer uma reflexão completaApenas para ajudar futuras pesquisas, o is_subclass_of também é uma boa variante (para PHP 5.3.7+):
fonte
Você também pode fazer o seguinte
Irá gerar um erro recuperável se o
$objectSupposedToBeImplementing
não implementar aYourInterface
interface.fonte
Atualizar
A
is_a
função está faltando aqui como alternativa.Fiz alguns testes de desempenho para verificar qual das maneiras declaradas é a mais eficiente.
Resultados com mais de 100 mil iterações
Foram adicionados alguns pontos para realmente "sentir" ver a diferença.
Gerado por isso: https://3v4l.org/8Cog7
Conclusão
Caso você tenha um objeto para verificar, use
instance of
como mencionado na resposta aceita.Caso você tenha uma turma para verificar, use
is_a
.Bônus
Dado o caso em que você deseja instanciar uma classe com base em uma interface que você precisa, é mais recomendável usar
is_a
. Há apenas uma exceção - quando o construtor está vazio.Exemplo:
is_a(<className>, <interfaceName>, true);
Voltará
bool
. O terceiro parâmetro " allow_string " permite verificar os nomes das classes sem instanciar a classe.fonte