Je sais que instanceof
c'est un opérateur et c'est is_a
une méthode.
Les performances de la méthode sont-elles plus lentes? Que préférez-vous utiliser?
Je sais que instanceof
c'est un opérateur et c'est is_a
une méthode.
Les performances de la méthode sont-elles plus lentes? Que préférez-vous utiliser?
Réponses:
Mettre à jour
Depuis PHP 5.3.9 , la fonctionnalité de is_a()
a changé. La réponse d'origine ci-dessous indique que is_a()
doit accepter un Object
comme premier argument, mais les versions PHP> = 5.3.9 acceptent désormais un troisième argument booléen facultatif $allow_string
(par défaut false
) pour permettre des comparaisons de noms de classe de chaînes à la place:
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 principale différence dans le nouveau comportement entre instanceof
et is_a()
est qu'il instanceof
vérifie toujours que la cible est un objet instancié de la classe spécifiée (y compris les classes d'extension), alors qu'il is_a()
ne nécessite que l'objet soit instancié lorsque l' $allow_string
argument est défini sur la valeur par défaut de false
.
Original
En fait, is_a
c'est une fonction, alors que instanceof
c'est une construction de langage. is_a
sera beaucoup plus lent (car il a tous les frais généraux d'exécution d'un appel de fonction), mais le temps d'exécution global est minimal dans l'une ou l'autre méthode.
Il n'est plus obsolète à partir de la version 5.3, il n'y a donc pas de souci là-bas.
Il y a cependant une différence. is_a
être une fonction prend un objet comme paramètre 1 et une chaîne (variable, constante ou littérale) comme paramètre 2. Donc:
is_a($object, $string); // <- Only way to call it
instanceof
prend un objet comme paramètre 1 et peut prendre un nom de classe (variable), une instance d'objet (variable) ou un identificateur de classe (nom de classe écrit sans guillemets) comme paramètre 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_a
obsolète?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
l' instanceof
opérateur est qu'il is_a
acceptera des expressions pour le deuxième paramètre, tandis que instanceof ne le fera pas. Par exemple, is_a($object, 'Prefix_'.$name)
fonctionne tout en $object instanceof 'Prefix_'.$name
ne pas
is_a
n'aurait jamais dû être déprécié en premier lieu. Il est un peu tard pour le réparer maintenant. Le problème est que l' instanceof
opérateur jette des erreurs de syntaxe dans PHP 4, et depuis qu'il is_a
était obsolète en même temps que l'opérateur a été introduit, il est devenu impossible d'écrire du code pour PHP 4 et 5 sans lancer un E_STRICT. Vous ne pouvez même pas le faire if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
car cela provoquerait toujours une erreur de syntaxe en PHP 4.
Voici les résultats de performance de is_a () et instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
La source du test est ici .
php 7
il n'y a pas de différence.
instanceof
peut être utilisé avec d'autres instances d'objet, le nom de la classe ou une interface. Je ne pense pas que cela (Mise à jour: voir https://gist.github.com/1455148 )is_a()
fonctionne avec les interfaces (seulement une chaîne représentant un nom de classe), mais corrigez-moi si c'est le cas.
Exemple 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'
les sorties:
bool(true)
bool(true)
bool(false)
is_a
fonctionne avec les interfaces de la même manière que instanceof
(j'allais dire la même chose, mais je l'ai vérifié avant de soumettre, et cela fonctionne en effet) ...
En ce qui concerne la réponse de ChrisF, is_a()
n'est plus obsolète depuis PHP 5.3.0. Je trouve qu'il est toujours plus sûr de consulter la source officielle pour des choses comme ça.
En ce qui concerne votre question, Daniel, je ne peux pas dire sur les différences de performances, mais une partie se résumera à la lisibilité et avec laquelle vous trouverez plus facile à travailler.
En outre, il y a une discussion au sujet de la confusion autour de la négation d' un instanceof
chèque vs is_a()
. Par exemple, instanceof
vous feriez:
<?php
if( !($a instanceof A) ) { //... }
?>
vs ce qui suit pour is_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
ou
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Modifier On dirait que ChrisF a supprimé sa réponse, mais la première partie de ma réponse est toujours valable.
Outre la vitesse, une autre différence importante réside dans la façon dont ils gèrent les boîtiers de bord.
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.
Ainsi, is_a () met en évidence les bogues possibles tandis que instanceof les supprime.
L'optimisation est minime. Et les micro-optimisations ne sont jamais une vraie bonne réponse, devant la lisibilité, l'intelligibilité et la stabilité du code.
(personnellement, je préfère l' instance , mais le choix vous appartient;))
La principale différence est la possibilité d'utiliser un nom de classe direct avec instanceof
$ une instance de MyClass
est plus court que
is_a ($ a, MyClass :: class)
(ok… ce n'est pas anodin.)
La coloration syntaxique entre instanceof (structure du langage) et is_a est également utile (pour moi). laissant la fonction colorer à des opérations plus importantes. Et pour une utilisation unique dans if, instanceof n'a pas besoin de plus de parenthèses.
Remarque: Bien sûr, au lieu de MyClass :: class, vous pouvez utiliser une chaîne directe plus courte:
is_a ($ a, 'MaClasse')
Mais utiliser une chaîne directe dans un code n'est pas une bonne pratique .
La collation syntaxique est meilleure et plus utile si vous pouvez faire la différence entre une chaîne simple et des noms de classes. Et il est plus facile de changer les noms avec un nom de classe constant. Spécialement si vous utilisez un espace de noms avec un alias.
Alors, pourquoi utiliser is_a () ?
Pour la même raison: lisibilité et incompréhension. (à vous de choisir) Spécialement utilisé avec ! ou d'autres opérateurs booléens: is_a semble plus pratique avec des parenthèses.
if ($ a AND (! is_a ($ a, MyClass :: class) OR is_a ($ a, MyOtherClass :: class))))
est plus lisible que:
if ($ a AND (! ($ a instanceof MyClass) OR ($ a intanceof MyOtherClass))))
Une autre bonne raison est lorsque vous devez utiliser le rappel dans les fonctions. (comme array_map …) instanceof n'est pas une fonction, c'est une construction de langage, vous ne pouvez donc pas l'utiliser comme rappel.
Dans ces cas, is_a peut être utile
Je ne peux pas parler de performance - je n'ai encore rien mesuré - mais selon ce que vous essayez, il y a des limites avec instanceof
. Découvrez ma question, récemment, à ce sujet:
PHP 'instanceof' échoue avec la constante de classe
J'ai fini par utiliser à la is_a
place. J'aime la structure de instanceof
mieux (je pense que ça se lit mieux) et je continuerai de l'utiliser quand je le pourrai.
Voici les résultats de performance obtenus à partir d' ici :
instanceof
est plus rapide.
Les fonctions
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';
}
Heures (exécutées 5000 fois chacune)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
Il existe un scénario où seul is_a()
fonctionne et instanceof
échouera.
instanceof
attend un nom de classe littéral ou une variable qui est soit un objet soit une chaîne (avec le nom d'une classe) comme argument de droite.
Mais si vous souhaitez fournir la chaîne d'un nom de classe à partir d'un appel de fonction, cela ne fonctionnera pas et entraînera une erreur de syntaxe.
Cependant, le même scénario fonctionne bien avec is_a()
.
Exemple:
<?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()));
Ceci est basé sur PHP 7.2.14.