¿Cuál es la diferencia entre is a e instanceof?


Soy consciente de que instanceof es un operador y que is_a es un método.

¿ Es el método más lento en rendimiento? ¿Qué preferirías usar?

 171
php
Author: Sk8erPeter, 2010-06-10

8 answers

En realidad, is_a es una función, mientras que instanceof es una construcción de lenguaje. is_a será significativamente más lento (ya que tiene toda la sobrecarga de ejecutar una llamada a una función), pero el tiempo de ejecución general es mínimo en cualquiera de los métodos.

Ya no está en desuso a partir de la versión 5.3, por lo que no hay que preocuparse.

Hay una diferencia, sin embargo. is_a siendo 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
 182
Author: ircmaxell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-06 20:37:10

Aquí está 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 es aquí.

 41
Author: Alexander Yancharuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-01 15:12:30

instanceof se puede usar con otras instancias de objetos, el nombre de la clase o una interfaz. No creo que is_a() funcione con interfaces (solo una cadena que representa un nombre de clase), pero corríjame si lo hace. (Actualización: Ver https://gist.github.com/1455148)

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)
 8
Author: Lotus Notes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-22 13:02:51

Con respecto a la respuesta de ChrisF, is_a() ya no está en desuso a partir de PHP 5.3.0. Me parece que siempre es más seguro ir por la fuente oficial para cosas como esta.

Con respecto a su pregunta, Daniel, no puedo decir acerca de las diferencias de rendimiento, pero parte de ella se reducirá a la facilidad y que usted encuentra más fácil de trabajar con.

También, hay cierta discusión sobre la confusión alrededor de negar un instanceof cheque vs is_a(). Por ejemplo, para instanceof usted 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) { //... }
?>

Edit Parece que ChrisF borró su respuesta, pero la primera parte de mi respuesta sigue en pie.

 4
Author: Mike Branski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-07 11:44:32

Además de la velocidad, otra diferencia importante es cómo manejan los casos de borde.

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 instanceof los suprime.

 4
Author: Csongor Halmai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 00:31:24

La optimización es mínima. Y las microoptimizaciones nunca son una respuesta realmente buena, frente a la legibilidad, comprensibilidad y estabilidad del código.

(personalmente prefiero instanceof , pero la elección es tuya;))

La principal diferencia es la posibilidad de usar el nombre de clase directo con instanceof

A una instancia de MyClass

Es más corto que

Is_a (a a, MyClass::class)

(ok… no es trivial. )

La coloración sintáxica entre instanceof (estructura del lenguaje) e is_a también es útil (para mí). dejando el color de la función a operaciones más grandes. Y para un solo uso en if, instanceof dosn 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 a,'MyClass')

Pero usar string directo en un código no es una buena práctica.

La coloración sintáxica es mejor y más útil si se puede hacer una diferencia entre la cadena simple y los nombres de las clases. Y es más fácil cambiar nombres con la constante classname. Especialy si utiliza espacio de nombres con alias.

Entonces, ¿por qué usar is_a()?

Para la misma razón : legibilidad e indestandabilidad. (la elección es tuya) Specialy cuando se utiliza con ! u otros operadores booleanos : is_a parece más práctico con paréntesis.

If (a a Y (!is_a (a a, MyClass:: class) O is_a (a a, MyOtherClass::class)))

Es más legible que :

If (a a Y (!(inst una instancia de mi Clase) O (a una instancia de mi otra clase)))

Otra buena razón es cuando necesita usar callback en funciones. ( como array_map … ) instanceof no es una función, es una construcción de lenguaje, por lo que no se puede utilizar como devolución de llamada.

En los casos, is_a puede ser útil

 2
Author: Titsta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-02 12:18:41

No puedo hablar de rendimiento yet aún no he medido nada yet pero dependiendo de lo que esté intentando, hay limitaciones con instanceof. Echa un vistazo a mi pregunta, recientemente, al respecto:

PHP 'instanceof' fallando con la constante de clase

He terminado usando is_a en su lugar. Me gusta más la estructura de instanceof (creo que se lee mejor) y continuaré usándola donde pueda.

 1
Author: Nathan Loding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:09

Aquí están los resultados de rendimiento obtenidos de aquí :

instanceof es más rápido.

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 (ejecutar 5000 veces cada uno)

0.00573397 // method_1(5) 
0.01437402 // method_2(5) 
0.00376201 // method_3(5)
 1
Author: dayuloli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-03 04:49:51