Soy consciente de que instanceofes un operador y que is_aes un método.
¿Es el método más lento en rendimiento? ¿Qué preferirías usar?
Soy consciente de que instanceofes un operador y que is_aes un método.
¿Es el método más lento en rendimiento? ¿Qué preferirías usar?
Respuestas:
Actualizar
A partir de PHP 5.3.9 , la funcionalidad de is_a()ha cambiado. La respuesta original a continuación establece que is_a() debe aceptar un Objectcomo primer argumento, pero las versiones de PHP> = 5.3.9 ahora aceptan un tercer argumento booleano opcional $allow_string(por defecto false) para permitir comparaciones de nombres de clase de cadena en su lugar:
class MyBaseClass {}
class MyExtendingClass extends MyBaseClass {}
// Original behavior, evaluates to false.
is_a(MyExtendingClass::class, MyBaseClass::class);
// New behavior, evaluates to true.
is_a(MyExtendingClass::class, MyBaseClass::class, true);
La diferencia clave en el nuevo comportamiento entre instanceofy is_a()es que instanceofsiempre comprobará que el objetivo es un objeto instanciado de la clase especificada (incluidas las clases extendidas), mientras que is_a()solo requiere que el objeto se instancia cuando el $allow_stringargumento se establece en el valor predeterminado de false.
Original
En realidad, is_aes una función, mientras que instanceofes una construcción del lenguaje. is_aserá significativamente más lento (ya que tiene toda la sobrecarga de ejecutar una llamada de función), pero el tiempo de ejecución general es mínimo en cualquier método.
Ya no está en desuso a partir de 5.3, por lo que no hay que preocuparse.
Sin embargo, hay una diferencia. is_aser una función toma un objeto como parámetro 1 y una cadena (variable, constante o literal) como parámetro 2. Entonces:
is_a($object, $string); // <- Only way to call it
instanceof toma un objeto como parámetro 1 y puede tomar un nombre de clase (variable), instancia de objeto (variable) o identificador de clase (nombre de clase escrito sin comillas) como parámetro 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_adesaprobado?
$class = 'Foo'; var_dump($obj instanceof $class);
is_ael instanceofoperador es que is_aaceptará expresiones para el segundo parámetro, mientras que instancia de wont. Por ejemplo, is_a($object, 'Prefix_'.$name)funciona mientras $object instanceof 'Prefix_'.$nameno funciona
is_anunca debería haber sido desaprobado en primer lugar. Sin embargo, es un poco tarde para arreglarlo ahora. El problema es que el instanceofoperador arroja errores de sintaxis en PHP 4, y dado que is_afue desaprobado exactamente al mismo tiempo que se introdujo el operador, se hizo imposible escribir código para PHP 4 y 5 sin lanzar un E_STRICT. Ni siquiera puede hacerlo if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }porque aún causaría un error de sintaxis en PHP 4.
Aquí están los resultados de rendimiento de is_a () y instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
La fuente de prueba está aquí .
php 7no hay diferencia.
instanceofse puede usar con otras instancias de objetos, el nombre de la clase o una interfaz. No creo que (Actualización: consulte https://gist.github.com/1455148 )is_a()funcione con interfaces (solo una cadena que representa un nombre de clase), pero corrígeme si lo hace.
Ejemplo de php.net :
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'
salidas:
bool(true)
bool(true)
bool(false)
is_afunciona con interfaces de la misma manera que instanceof(iba a decir lo mismo, pero lo verifiqué antes de enviarlo, y de hecho funciona) ...
En lo que respecta a la respuesta de ChrisF, is_a() ya no está en desuso a partir de PHP 5.3.0. Creo que siempre es más seguro recurrir a la fuente oficial para cosas como esta.
Con respecto a su pregunta, Daniel, no puedo decir sobre las diferencias de rendimiento, pero parte de esto se reducirá a la legibilidad y con la que le resultará más fácil trabajar.
Además, existe cierto debate acerca de la confusión en torno a la negación de un instanceofcheque vs is_a(). Por ejemplo, para instanceofusted haría:
<?php
if( !($a instanceof A) ) { //... }
?>
vs lo siguiente para is_a():
<?php
if( !is_a($a, 'A' ) { //... }
?>
o
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Editar Parece que ChrisF eliminó su respuesta, pero la primera parte de mi respuesta sigue en pie.
Además de la velocidad, otra diferencia importante es cómo manejan los casos extremos.
is_a($x1, $x2) // fatal error if x2 is not a string nor an object
$x1 instanceof $x2 // returns false even if $x2 is int, undefined, etc.
Entonces, is_a () resalta posibles errores, mientras que instanceof los suprime.
La optimización es mínima. Y las micro optimizaciones nunca son una buena respuesta, frente a la legibilidad, la comprensión y la estabilidad del código.
(Personalmente prefiero instancia de , pero la elección es suya;))
La principal diferencia es la posibilidad de usar el nombre de clase directo con instanceof
$ una instancia de MyClass
es más corto que
is_a ($ a, MyClass :: class)
(ok ... no es trivial)
La coloración sintáctica entre instanceof (estructura del lenguaje) e is_a también es útil (para mí). dejando el color de la función para operaciones más grandes. Y para un solo uso en if, instancia de dos no necesita más paréntesis.
Nota: Por supuesto, en lugar de MyClass :: class puede usar una cadena directa más corta:
is_a ($ a, 'MyClass')
Pero usar una cadena directa en un código no es una buena práctica .
La colocación sintáctica es mejor y más útil si puede hacer una diferencia entre una cadena simple y nombres de clases. Y es más fácil cambiar nombres con nombre de clase constante. Especialmente si usa el espacio de nombres con alias.
Entonces, ¿por qué usar is_a () ?
Por la misma razón: legibilidad e inteligibilidad. (la elección es suya) Especialmente cuando se usa con ! u otros operadores booleanos: is_a parece más práctico con paréntesis.
if ($ a AND (! is_a ($ a, MyClass :: class) OR is_a ($ a, MyOtherClass :: class)))
es más legible que:
if ($ a AND (! ($ a instanceof MyClass) OR ($ a intanceof MyOtherClass)))
Otra buena razón es cuando necesita usar la devolución de llamada en las funciones. (como array_map ...) instanceof no es una función, es una construcción de lenguaje, por lo que no puede usarla como devolución de llamada.
En estos casos, is_a puede ser útil
No puedo hablar por el rendimiento, todavía no he medido nada, pero dependiendo de lo que esté intentando, existen limitaciones con instanceof . Mira mi pregunta, recientemente, al respecto:
PHP 'instanceof' falla con constante de clase
Terminé usando en su is_alugar. Me gusta la estructura de instanceofmejor (creo que se lee mejor) y continuaré usándola donde pueda.
Aquí están los resultados de rendimiento obtenidos de aquí :
instanceof es más rápido.
Las funciones
function method_1($a = null) {
return is_object($a) && is_a($a, 'Example');
}
function method_2($a = null) {
return is_a((object) $a, 'Example');
}
function method_3($a = null) {
return $a instanceof 'Example';
}
Tiempos (ejecutados 5000 veces cada uno)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
Hay un escenario donde solo is_a()funciona y instanceoffallará.
instanceof espera un nombre de clase literal o una variable que sea un objeto o una cadena (con el nombre de una clase) como argumento correcto.
Pero si desea proporcionar la cadena de un nombre de clase de una llamada de función, no funcionará y dará como resultado un error de sintaxis.
Sin embargo, el mismo escenario funciona bien con is_a().
Ejemplo:
<?php
function getClassName() : string
{
return "Foobar";
}
class Foobar
{
private $xyz;
}
$x = new Foobar();
// this works of course
var_dump($x instanceof Foobar);
// this creates a syntax error
var_dump($x instanceof getClassName());
// this works
var_dump(is_a($x, getClassName()));
Esto se basa en PHP 7.2.14.