Ich bin mir bewusst, dass instanceof ein Operator und is_aeine Methode ist.
Ist die Leistung der Methode langsamer? Was würdest du lieber benutzen?
Ich bin mir bewusst, dass instanceof ein Operator und is_aeine 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 , ObjectPHP-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 instanceofund is_a()besteht darin, dass instanceofimmer ü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_stringArgument auf den Standardwert von gesetzt ist false.
Original
Eigentlich is_aist eine Funktion, während instanceofes sich um ein Sprachkonstrukt handelt. is_awird 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_aAls 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_averaltet?
$class = 'Foo'; var_dump($obj instanceof $class);
is_agegenüber dem instanceofOperator beachten sollten , ist, dass is_aAusdrü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_'.$namenicht
is_asollte niemals in erster Linie veraltet sein. Es ist allerdings etwas spät, das Problem jetzt zu beheben. Das Problem ist, dass der instanceofOperator Syntaxfehler in PHP 4 is_aauslö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 7gibt es keinen Unterschied.
instanceofkann 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_afunktioniert 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 instanceofScheck vs is_a(). Zum Beispiel instanceofwü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_astattdessen verwendet. Ich mag die Struktur von instanceofbesser (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 instanceoffehlschlä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.