Ich bin mir bewusst, dass instanceof
ein Operator und is_a
eine Methode ist.
Ist die Leistung der Methode langsamer? Was würdest du lieber benutzen?
Ich bin mir bewusst, dass instanceof
ein Operator und is_a
eine Methode ist.
Ist die Leistung der Methode langsamer? Was würdest du lieber benutzen?
Antworten:
Aktualisieren
Ab PHP 5.3.9 hat sich die Funktionalität von is_a()
geändert. Die ursprüngliche Antwort unten besagt, dass ein als erstes Argument akzeptiert werden is_a()
muss , Object
PHP-Versionen> = 5.3.9 akzeptieren jetzt jedoch ein optionales drittes boolesches Argument $allow_string
(standardmäßig false
), um stattdessen Vergleiche von Zeichenfolgenklassennamen zu ermöglichen:
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);
Der Hauptunterschied im neuen Verhalten zwischen instanceof
und is_a()
besteht darin, dass instanceof
immer überprüft wird, ob das Ziel ein instanziiertes Objekt der angegebenen Klasse ist (einschließlich erweiterter Klassen), während is_a()
das Objekt nur instanziiert werden muss, wenn das $allow_string
Argument auf den Standardwert von gesetzt ist false
.
Original
Eigentlich is_a
ist eine Funktion, während instanceof
es sich um ein Sprachkonstrukt handelt. is_a
wird erheblich langsamer sein (da der gesamte Aufwand für die Ausführung eines Funktionsaufrufs anfällt), aber die Gesamtausführungszeit ist bei beiden Methoden minimal.
Ab 5.3 ist es nicht mehr veraltet, daher gibt es dort keine Sorgen mehr.
Es gibt jedoch einen Unterschied. is_a
Als Funktion wird ein Objekt als Parameter 1 und eine Zeichenfolge (Variable, Konstante oder Literal) als Parameter 2 verwendet. Also:
is_a($object, $string); // <- Only way to call it
instanceof
Nimmt ein Objekt als Parameter 1 und kann einen Klassennamen (Variable), eine Objektinstanz (Variable) oder eine Klassenkennung (Klassenname ohne Anführungszeichen) als Parameter 2 verwenden.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_a
veraltet?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
gegenüber dem instanceof
Operator beachten sollten , ist, dass is_a
Ausdrücke für den zweiten Parameter akzeptiert werden, während dies nicht der Fall ist. Zum Beispiel is_a($object, 'Prefix_'.$name)
funktioniert, während $object instanceof 'Prefix_'.$name
nicht
is_a
sollte niemals in erster Linie veraltet sein. Es ist allerdings etwas spät, das Problem jetzt zu beheben. Das Problem ist, dass der instanceof
Operator Syntaxfehler in PHP 4 is_a
auslöst. Da dies genau zur gleichen Zeit veraltet war, als der Operator eingeführt wurde, war es unmöglich, Code für PHP 4 und 5 zu schreiben, ohne ein E_STRICT herumzuwerfen. Sie können nicht einmal tun, if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
weil es immer noch einen Syntaxfehler in PHP 4 verursachen würde.
Hier sind die Leistungsergebnisse von is_a () und instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Testquelle ist hier .
php 7
gibt es keinen Unterschied.
instanceof
kann mit anderen Objektinstanzen, dem Klassennamen oder einer Schnittstelle verwendet werden. Ich denke nicht, dass (Update: Siehe https://gist.github.com/1455148 )is_a()
das mit Schnittstellen funktioniert (nur eine Zeichenfolge, die einen Klassennamen darstellt), aber korrigiere mich, wenn dies der Fall ist.
Beispiel von 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'
Ausgänge:
bool(true)
bool(true)
bool(false)
is_a
funktioniert mit Schnittstellen genauso wie instanceof
(ich wollte dasselbe sagen, aber ich habe es vor dem Absenden überprüft, und es funktioniert tatsächlich) ...
In Bezug auf die Antwort von ChrisF ist ab PHP 5.3.0 is_a()
nicht mehr veraltet . Ich finde es immer sicherer, sich für solche Dinge an die offizielle Quelle zu wenden.
In Bezug auf Ihre Frage, Daniel, kann ich nichts über die Leistungsunterschiede sagen, aber ein Teil davon hängt von der Lesbarkeit ab, mit der Sie leichter arbeiten können.
Auch gibt es einige Diskussionen über die Verwirrung um negiert einen instanceof
Scheck vs is_a()
. Zum Beispiel instanceof
würden Sie tun:
<?php
if( !($a instanceof A) ) { //... }
?>
vs die folgenden für is_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
oder
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Bearbeiten Sieht so aus, als hätte ChrisF seine Antwort gelöscht, aber der erste Teil meiner Antwort steht noch.
Neben der Geschwindigkeit ist ein weiterer wichtiger Unterschied, wie sie mit Kantenfällen umgehen.
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.
Is_a () hebt mögliche Fehler hervor, während die Instanz sie unterdrückt.
Die Optimierung ist minimal. Und Mikrooptimierungen sind angesichts der Lesbarkeit, Verständlichkeit und Stabilität des Codes niemals eine wirklich gute Antwort.
(Ich persönlich bevorzuge eine Instanz davon , aber die Wahl liegt bei Ihnen;))
Der Hauptunterschied besteht in der Möglichkeit, den direkten Klassennamen mit instanceof zu verwenden
$ eine Instanz von MyClass
ist kürzer als
is_a ($ a, MyClass :: class)
(ok ... es ist nicht trivial.)
Die syntaktische Färbung zwischen instanceof (Sprachstruktur) und is_a ist ebenfalls nützlich (für mich). Funktionsfarbe für größere Operationen verwenden. Und für den einmaligen Gebrauch, wenn zum Beispiel nicht mehr Klammern benötigt werden.
Hinweis: Natürlich können Sie anstelle von MyClass :: class auch eine kürzere direkte Zeichenfolge verwenden:
is_a ($ a, 'MyClass')
Die Verwendung einer direkten Zeichenfolge in einem Code ist jedoch keine gute Vorgehensweise .
Die syntaktische Sortierung ist besser und nützlicher, wenn Sie zwischen einfachen Zeichenfolgen- und Klassennamen unterscheiden können. Und es ist einfacher, Namen mit konstantem Klassennamen zu ändern. Besonders, wenn Sie einen Namespace mit Alias verwenden.
Also, warum is_a () verwenden ?
Aus demselben Grund: Lesbarkeit und Verständlichkeit. (Sie haben die Wahl) Spezial bei Verwendung mit ! oder andere boolesche Operatoren: is_a scheint mit Klammern praktischer zu sein.
if ($ a AND (! is_a ($ a, MyClass :: class) ODER is_a ($ a, MyOtherClass :: class)))
ist besser lesbar als:
if ($ a AND (! ($ a Instanz von MyClass) OR ($ a Intance von MyOtherClass)))
Ein weiterer guter Grund ist, wenn Sie Rückruf in Funktionen verwenden müssen. (wie array_map …) instanceof ist keine Funktion, sondern ein Sprachkonstrukt, daher können Sie es nicht als Rückruf verwenden.
In diesen Fällen kann is_a nützlich sein
Ich kann nicht für Leistung sprechen - ich habe noch nichts gemessen - aber je nachdem, was Sie versuchen, gibt es Einschränkungen bei instanceof
. Schauen Sie sich erst kürzlich meine Frage dazu an:
PHP 'instanceof' schlägt mit Klassenkonstante fehl
Ich habe is_a
stattdessen verwendet. Ich mag die Struktur von instanceof
besser (ich denke, sie liest sich besser) und werde sie weiterhin verwenden, wo ich kann.
Hier sind die Leistungsergebnisse, die Sie hier erhalten :
instanceof
ist schneller.
Funktionen
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';
}
Zeiten (jeweils 5000 Mal ausgeführt)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
Es gibt ein Szenario, in dem nur is_a()
funktioniert und instanceof
fehlschlägt.
instanceof
erwartet einen Literalklassennamen oder eine Variable, die entweder ein Objekt oder eine Zeichenfolge (mit dem Namen einer Klasse) als rechtes Argument ist.
Wenn Sie jedoch die Zeichenfolge eines Klassennamens aus einem Funktionsaufruf bereitstellen möchten, funktioniert dies nicht und führt zu einem Syntaxfehler.
Das gleiche Szenario funktioniert jedoch einwandfrei is_a()
.
Beispiel:
<?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()));
Dies basiert auf PHP 7.2.14.