Sono consapevole che instanceofè un operatore e che is_aè un metodo.
Il metodo è più lento nelle prestazioni? Cosa preferiresti usare?
Sono consapevole che instanceofè un operatore e che is_aè un metodo.
Il metodo è più lento nelle prestazioni? Cosa preferiresti usare?
Risposte:
Aggiornare
A partire da PHP 5.3.9 , la funzionalità di is_a()è cambiata. La risposta originale di seguito afferma che is_a() deve accettare un Objectcome primo argomento, ma le versioni di PHP> = 5.3.9 ora accettano un terzo argomento booleano opzionale $allow_string(predefinito su false) per consentire invece il confronto dei nomi delle classi di stringhe:
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 differenza chiave nel nuovo comportamento tra instanceofe is_a()è che instanceofcontrollerà sempre che la destinazione è un oggetto istanziato della classe specificata (comprese le classi estese), mentre is_a()richiede che l'oggetto sia istanziato solo quando l' $allow_stringargomento è impostato sul valore predefinito di false.
Originale
In realtà, is_aè una funzione, mentre instanceofè un costrutto linguistico. is_asarà significativamente più lento (poiché ha tutto il sovraccarico dell'esecuzione di una chiamata di funzione), ma il tempo di esecuzione complessivo è minimo in entrambi i metodi.
Non è più obsoleto a partire dalla 5.3, quindi non c'è preoccupazione.
C'è comunque una differenza. is_aessendo una funzione accetta un oggetto come parametro 1 e una stringa (variabile, costante o letterale) come parametro 2. Quindi:
is_a($object, $string); // <- Only way to call it
instanceof accetta un oggetto come parametro 1 e può assumere un nome di classe (variabile), un'istanza di oggetto (variabile) o un identificatore di classe (nome di classe scritto senza virgolette) come parametro 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_adichiarato?
$class = 'Foo'; var_dump($obj instanceof $class);
is_arispetto instanceofall'operatore è che is_aaccetterà espressioni per il secondo parametro, mentre d'istanza non lo farà. Ad esempio is_a($object, 'Prefix_'.$name)funziona mentre $object instanceof 'Prefix_'.$namenon lo fa
is_amai avrebbe dovuto essere deprecato in primo luogo. Ma è un po 'tardi per risolverlo adesso. Il problema è che l' instanceofoperatore genera errori di sintassi in PHP 4 e poiché è is_astato deprecato nello stesso momento in cui l'operatore è stato introdotto, è diventato impossibile scrivere codice sia per PHP 4 che per 5 senza lanciare un E_STRICT. Non puoi nemmeno farlo if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }perché causerebbe comunque un errore di sintassi in PHP 4.
Ecco i risultati delle prestazioni di is_a () e instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
La fonte del test è qui .
php 7non c'è differenza.
instanceofpuò essere utilizzato con altre istanze di oggetto, il nome della classe o un'interfaccia. Non penso che (Aggiornamento: vedi https://gist.github.com/1455148 )is_a()funzioni con le interfacce (solo una stringa che rappresenta un nome di classe), ma correggimi se lo fa.
Esempio da 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'
uscite:
bool(true)
bool(true)
bool(false)
is_afunziona con le interfacce nello stesso modo di instanceof(stavo per dire la stessa cosa, ma l'ho verificato prima di
Per quanto riguarda la risposta di ChrisF, is_a() non è più deprecato a partire da PHP 5.3.0. Trovo che sia sempre più sicuro andare dalla fonte ufficiale per cose come questa.
Per quanto riguarda la tua domanda, Daniel, non posso dire delle differenze di prestazione, ma parte di essa dipenderà dalla leggibilità e con la quale troverai più facile lavorare.
Inoltre, v'è una certa discussione circa la confusione intorno a negare un instanceofcontrollo vs is_a(). Ad esempio, per instanceofte farebbe:
<?php
if( !($a instanceof A) ) { //... }
?>
vs quanto segue per is_a():
<?php
if( !is_a($a, 'A' ) { //... }
?>
o
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Modifica Sembra che ChrisF abbia eliminato la sua risposta, ma la prima parte della mia risposta è ancora valida.
Oltre alla velocità, un'altra differenza importante è il modo in cui gestiscono i casi limite.
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.
Quindi, is_a () evidenzia possibili bug mentre instanceof li elimina.
L'ottimizzazione è minima. E le microottimizzazioni non sono mai una vera buona risposta, di fronte alla leggibilità, comprensibilità e stabilità del codice.
(personalmente preferisco istanza di , ma la scelta è tua;))
La differenza principale è la possibilità di usare il nome di classe diretto con instanceof
$ un'istanza di MyClass
è più corto di
is_a ($ a, MyClass :: class)
(ok ... non è banale.)
Anche la colorazione sintattica tra instanceof (struttura del linguaggio) e is_a è utile (per me). lasciando che il colore funzioni a operazioni più grandi. E per uso singolo in if, instanceof non necessita di più parentesi.
Nota: ovviamente invece di MyClass :: class puoi usare una stringa diretta più corta:
is_a ($ a, 'MyClass')
Ma usare la stringa diretta in un codice non è una buona pratica .
La collazione sintattica è migliore e più utile se puoi fare la differenza tra nomi di stringhe e classi semplici. Ed è più facile cambiare i nomi con un nome di classe costante. In particolare se si utilizza lo spazio dei nomi con alias.
Quindi, perché usare is_a () ?
Per lo stesso ragionamento: leggibilità e instabilità. (a te la scelta) Se usato con ! o altri operatori booleani: is_a sembra più pratico tra parentesi.
if ($ a AND (! is_a ($ a, MyClass :: class) OR is_a ($ a, MyOtherClass :: class)))
è più leggibile di:
if ($ a AND (! ($ a instanceof MyClass) OR ($ a intanceof MyOtherClass)))
Un altro buon motivo è quando è necessario utilizzare la richiamata nelle funzioni. (come array_map ...) instanceof non è una funzione, è un costrutto di linguaggio, quindi non puoi usarlo come callback.
In questi casi, is_a può essere utile
Non posso parlare di prestazioni - non ho ancora misurato nulla - ma a seconda di ciò che stai tentando, ci sono delle limitazioni instanceof . Dai un'occhiata alla mia domanda, proprio di recente, al riguardo:
PHP "instanceof" non riuscito con costante di classe
Ho finito per usare is_ainvece. Mi piace la struttura del instanceofmeglio (penso che sia più bella) e continuerò ad usarla dove posso.
Ecco i risultati delle prestazioni ottenuti da qui :
instanceof è più veloce.
funzioni
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';
}
Tempi (eseguire 5000 volte ciascuno)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
C'è uno scenario in cui is_a()funziona solo e instanceoffallirà.
instanceof si aspetta un nome di classe letterale o una variabile che sia un oggetto o una stringa (con il nome di una classe) come argomento corretto.
Ma se si desidera fornire la stringa di un nome di classe da una chiamata di funzione, non funzionerà e si verificherà un errore di sintassi.
Tuttavia, lo stesso scenario funziona bene con is_a().
Esempio:
<?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()));
Questo si basa su PHP 7.2.14.