Wiem, że instanceof
to operator i to is_a
jest metoda.
Czy metoda działa wolniej? Z czego wolisz korzystać?
Wiem, że instanceof
to operator i to is_a
jest metoda.
Czy metoda działa wolniej? Z czego wolisz korzystać?
Odpowiedzi:
Aktualizacja
Od wersji PHP 5.3.9is_a()
zmieniła się funkcjonalność . Oryginalna odpowiedź poniżej stwierdza, że is_a()
musi przyjąć Object
jako pierwszy argument, ale wersje PHP> = 5.3.9 akceptują teraz opcjonalny trzeci argument boolowski $allow_string
(domyślnie to false
), aby zamiast tego umożliwić porównanie nazw klas łańcuchów:
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);
Kluczowa różnica w nowym zachowaniu między instanceof
i is_a()
polega na tym, instanceof
że zawsze sprawdzi, czy obiekt docelowy jest utworzonym obiektem określonej klasy (w tym klas rozszerzających), podczas gdy is_a()
wymaga tylko utworzenia obiektu, gdy $allow_string
argument jest ustawiony na wartość domyślną false
.
Oryginalny
W rzeczywistości is_a
jest funkcją, podczas gdy instanceof
jest konstrukcją językową. is_a
będzie znacznie wolniejszy (ponieważ ma cały narzut związany z wykonaniem wywołania funkcji), ale ogólny czas wykonania jest minimalny w każdej z metod.
Nie jest już przestarzałe od 5.3, więc nie ma się co martwić.
Jest jednak jedna różnica. is_a
bycie funkcją przyjmuje obiekt jako parametr 1, a ciąg (zmienny, stały lub literał) jako parametr 2. Zatem:
is_a($object, $string); // <- Only way to call it
instanceof
przyjmuje obiekt jako parametr 1 i może przyjmować nazwę klasy (zmienną), instancję obiektu (zmienną) lub identyfikator klasy (nazwę klasy zapisaną bez cudzysłowów) jako parametr 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_a
nieaktualny?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
vs instanceof
operator jest to, że is_a
akceptuje wyrażenia dla drugiego parametru, podczas gdy instanceof nie będzie. Na przykład is_a($object, 'Prefix_'.$name)
działa, podczas gdy $object instanceof 'Prefix_'.$name
nie działa
is_a
nigdy nie powinien był być przestarzały. Jednak teraz jest trochę za późno, aby to naprawić. Problem polega na tym, że instanceof
operator zgłasza błędy składniowe w PHP 4, a ponieważ is_a
był przestarzały w tym samym czasie, w którym wprowadzono operatora, stało się niemożliwe napisanie kodu zarówno dla PHP 4, jak i 5 bez rzucania E_STRICT. Nie możesz tego zrobić, if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
ponieważ nadal powoduje błąd składniowy w PHP 4.
Oto wyniki wydajności is_a () i instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Źródło testu jest tutaj .
php 7
nie ma różnicy.
instanceof
może być używany z innymi instancjami obiektów, nazwą klasy lub interfejsem. Nie sądzę, że (Aktualizacja: patrz https://gist.github.com/1455148 )is_a()
działa z interfejsami (tylko ciąg znaków reprezentujący nazwę klasy), ale popraw mnie, jeśli to działa.
Przykład z 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'
wyjścia:
bool(true)
bool(true)
bool(false)
is_a
działa z interfejsami w taki sam sposób, jak instanceof
(chciałem powiedzieć to samo, ale sprawdziłem to przed przesłaniem i rzeczywiście działa) ...
Jeśli chodzi o odpowiedź ChrisF, is_a()
nie jest już przestarzała od PHP 5.3.0. Uważam, że zawsze bezpieczniej jest korzystać z oficjalnego źródła takich rzeczy.
Jeśli chodzi o twoje pytanie, Daniel, nie mogę powiedzieć o różnicach w wydajności, ale część z nich sprowadza się do czytelności i z którą łatwiej ci się pracuje.
Ponadto, istnieje pewna dyskusja na temat zamieszania wokół negując to instanceof
czek vs is_a()
. Na przykład dla instanceof
ciebie zrobiłbyś:
<?php
if( !($a instanceof A) ) { //... }
?>
vs następujące dla is_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
lub
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Edytuj Wygląda na to, że ChrisF usunął swoją odpowiedź, ale pierwsza część mojej odpowiedzi nadal obowiązuje.
Oprócz prędkości, inną ważną różnicą jest sposób, w jaki obsługują przypadki krawędzi.
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.
Zatem is_a () podkreśla możliwe błędy, a instanceof je eliminuje.
Optymalizacja jest minimalna. A mikrooptymalizacje nigdy nie są naprawdę dobrą odpowiedzią, pomimo czytelności, zrozumiałości i stabilności kodu.
(Ja osobiście preferujemy instancją , ale wybór należy do Ciebie;))
Główną różnicą jest możliwość użycia bezpośredniej nazwy klasy z instanceof
$ wystąpienie MyClass
jest krótszy niż
is_a ($ a, MyClass :: class)
(ok ... to nie jest banalne.)
Przydatne jest również składniowe kolorowanie między instanceof (struktura językowa) a is_a (dla mnie). pozwalając kolorowi funkcji na większe operacje. I do jednorazowego użytku, jeśli instanceof nie potrzebuje więcej nawiasów.
Uwaga: Oczywiście zamiast MyClass :: class możesz użyć krótszego ciągu bezpośredniego:
is_a ($ a, „MyClass”)
Ale użycie bezpośredniego ciągu w kodzie nie jest dobrą praktyką .
Składnia składniowa jest lepsza i bardziej użyteczna, jeśli można zrobić różnicę między prostymi nazwami łańcuchów i klas. I łatwiej jest zmieniać nazwy za pomocą stałej nazwy klasy. Zwłaszcza jeśli używasz przestrzeni nazw z aliasem.
Wy użyj is_a () ?
Z tej samej racji: czytelność i nierozpoznawalność. (wybór należy do Ciebie) Specjalnie, gdy używasz go ! lub inne operatory logiczne: is_a wydaje się bardziej praktyczne z nawiasami.
if ($ a AND (! is_a ($ a, MyClass :: class) OR is_a ($ a, MyOtherClass :: class)))
jest bardziej czytelny niż:
if ($ a AND (! ($ a instanceof MyClass) LUB ((a intanceof MyOtherClass))))
Innym dobrym powodem jest konieczność użycia funkcji zwrotnej w funkcjach. (jak array_map …) instanceof nie jest funkcją, jest konstrukcją językową, więc nie można jej użyć jako wywołania zwrotnego.
W takich przypadkach użyteczne może być is_a
Nie mogę mówić o wydajności - jeszcze niczego nie mierzyłem - ale w zależności od tego, co próbujesz, istnieją ograniczenia instanceof
. Sprawdź moje pytanie na ten temat:
PHP „instanceof” zawodzi ze stałą klasy
Skończyło się na tym, że używam is_a
. Podoba mi się struktura instanceof
lepiej (myślę, że jest ładniejsza) i nadal będę jej używać tam, gdzie mogę.
Oto wyniki wydajności uzyskane stąd :
instanceof
jest szybszy.
Funkcje
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';
}
Razy (uruchom 5000 razy każdy)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
Istnieje scenariusz, w którym is_a()
działa tylko i instanceof
zawiedzie.
instanceof
oczekuje literałowej nazwy klasy lub zmiennej, która jest albo obiektem albo łańcuchem (z nazwą klasy) jako właściwym argumentem.
Ale jeśli chcesz podać ciąg nazwy klasy z wywołania funkcji, nie będzie działać i spowoduje błąd składniowy.
Jednak ten sam scenariusz działa dobrze z is_a()
.
Przykład:
<?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()));
Jest to oparte na PHP 7.2.14.