Dada una instancia de clase, ¿es posible determinar si implementa una interfaz particular? Hasta donde sé, no hay una función integrada para hacer esto directamente. ¿Qué opciones tengo (si las hay)?
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Puede usar el operador "instanceof". Para usarlo, el operando izquierdo es una instancia de clase y el operando derecho es una interfaz. Devuelve verdadero si el objeto implementa una interfaz particular.
Como se señala a continuación, puede usar class_implements()
. Al igual que con Reflection, esto le permite especificar el nombre de la clase como una cadena y no requiere una instancia de la clase:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$interfaces = class_implements('TheClass');
if (isset($interfaces['IInterface'])) {
echo "Yes!";
}
class_implements()
es parte de la extensión SPL.
Ver: http://php.net/manual/en/function.class-implements.php
Algunas pruebas de rendimiento simples muestran los costos de cada enfoque:
Construcción de objetos fuera del ciclo (100,000 iteraciones) ____________________________________________ El | implementaciones de clase | Reflexión | instanceOf | | ------------------ | ------------ | ------------ | El | 140 ms | 290 ms | 35 ms | '--------------------------------------------' Construcción de objetos dentro del bucle (100,000 iteraciones) ____________________________________________ El | implementaciones de clase | Reflexión | instanceOf | | ------------------ | ------------ | ------------ | El | 182 ms | 340 ms | 83 ms | Constructor barato El | 431 ms | 607 ms | 338 ms | Constructor caro '--------------------------------------------'
100,000 iteraciones ____________________________________________ El | implementaciones de clase | Reflexión | instanceOf | | ------------------ | ------------ | ------------ | El | 149 ms | 295 ms | N / A '--------------------------------------------'
Donde el costoso __construct () es:
public function __construct() {
$tmp = array(
'foo' => 'bar',
'this' => 'that'
);
$in = in_array('those', $tmp);
}
Estas pruebas se basan en este código simple .
nlaq señala que instanceof
se puede usar para probar si el objeto es una instancia de una clase que implementa una interfaz.
Pero instanceof
no distingue entre un tipo de clase y una interfaz. No sabe si el objeto es una clase a la que se llama IInterface
.
También puede usar la API de reflexión en PHP para probar esto más específicamente:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
class_implements()
instanceof
volver a usar de forma segura .class_implements()
porque es obviamente más rápido llamar a class_implements y luego in_array, en lugar de hacer una reflexión completaSolo para ayudar a futuras búsquedas is_subclass_of también es una buena variante (para PHP 5.3.7+):
fuente
También puedes hacer lo siguiente
Lanzará un error recuperable si
$objectSupposedToBeImplementing
no implementa laYourInterface
interfaz.fuente
Actualizar
La
is_a
función falta aquí como alternativa.Hice algunas pruebas de rendimiento para verificar cuál de las formas indicadas es la más eficiente.
Resultados de más de 100k iteraciones
Se agregaron algunos puntos para realmente "sentir" ver la diferencia.
Generado por esto: https://3v4l.org/8Cog7
Conclusión
En caso de que tenga un objeto para verificar, use
instance of
como se menciona en la respuesta aceptada.En caso de que tenga una clase para verificar, use
is_a
.Prima
Dado el caso en el que desea crear una instancia de una clase basada en una interfaz que necesita, es más preformante de usar
is_a
. Solo hay una excepción: cuando el constructor está vacío.Ejemplo:
is_a(<className>, <interfaceName>, true);
Se volverá
bool
. El tercer parámetro " allow_string " le permite verificar los nombres de clase sin crear instancias de la clase.fuente