is_a () może działać wolniej - ale można go wywoływać za pomocą call_user_func (), podczas gdy instanceof nie może być wywoływany w ten sposób ...
Kamil Tomšík
Odpowiedzi:
211
Aktualizacja
Od wersji PHP 5.3.9is_a() zmieniła się funkcjonalność . Oryginalna odpowiedź poniżej stwierdza, że is_a()musi przyjąć Objectjako 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:
classMyBaseClass{}classMyExtendingClassextendsMyBaseClass{}// 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 instanceofi 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_stringargument jest ustawiony na wartość domyślną false.
Oryginalny
W rzeczywistości is_ajest funkcją, podczas gdy instanceofjest konstrukcją językową. is_abę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_abycie 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 instanceofClassName;// <- identifier for the class
Jeszcze jedną rzeczą wartą uwagi na temat is_avs instanceofoperator jest to, że is_aakceptuje 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_'.$namenie działa
Evan Purkhiser
6
is_anigdy nie powinien był być przestarzały. Jednak teraz jest trochę za późno, aby to naprawić. Problem polega na tym, że instanceofoperator zgłasza błędy składniowe w PHP 4, a ponieważ is_abył 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.
Innymi słowy, różnica jest ważna tylko wtedy, gdy trzeba zaoszczędzić ~ 0,015 sekundy na 10000 zastosowań.
CJ Dennis
1
Jak na razie php 7nie ma różnicy.
MAX
@CJDennis Z doświadczenia wynika, że gdy wszyscy tak myślą, końcowy produkt będzie wolniejszy niż oczekiwano. (Serwery Soft + OS + niezoptymalizowane). Pamiętaj, że dodany czas nie zawsze jest liniowy, ale może być wykładniczy. Zawsze miej na uwadze wydajność.
Toto
@Toto Istnieje doskonały wpis na blogu o tym, czego doświadczeni programiści mogą nauczyć się od początkujących. Mam nadzieję, że możesz to zobaczyć w prawym górnym rogu. Uwaga na przedwczesną optymalizację! Rozwiązuj problemy z synchronizacją dopiero, gdy stają się problemami ! Jeśli wydajność jest możliwa do zaakceptowania, nie marnuj czasu na jej zmianę!
CJ Dennis,
10
instanceofmoże być używany z innymi instancjami obiektów, nazwą klasy lub interfejsem. Nie sądzę, że is_a()działa z interfejsami (tylko ciąg znaków reprezentujący nazwę klasy), ale popraw mnie, jeśli to działa. (Aktualizacja: patrz https://gist.github.com/1455148 )
interfaceMyInterface{}classMyClassimplementsMyInterface{}
$a =newMyClass;
$b =newMyClass;
$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'
is_adział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) ...
ircmaxell
2
-1, proszę streścić aktualizację, a nie tylko link do istoty. To nie jest pomocne dla osób próbujących się uczyć.
Erick Robertson,
5
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 instanceofczek vs is_a(). Na przykład dla instanceofciebie 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.
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.
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:
Istnieje scenariusz, w którym is_a()działa tylko i instanceofzawiedzie.
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";}classFoobar{private $xyz;}
$x =newFoobar();// this works of course
var_dump($x instanceofFoobar);// this creates a syntax error
var_dump($x instanceof getClassName());// this works
var_dump(is_a($x, getClassName()));
Odpowiedzi:
Aktualizacja
Od wersji PHP 5.3.9
is_a()
zmieniła się funkcjonalność . Oryginalna odpowiedź poniżej stwierdza, żeis_a()
musi przyjąćObject
jako pierwszy argument, ale wersje PHP> = 5.3.9 akceptują teraz opcjonalny trzeci argument boolowski$allow_string
(domyślnie tofalse
), aby zamiast tego umożliwić porównanie nazw klas łańcuchów:Kluczowa różnica w nowym zachowaniu między
instanceof
iis_a()
polega na tym,instanceof
że zawsze sprawdzi, czy obiekt docelowy jest utworzonym obiektem określonej klasy (w tym klas rozszerzających), podczas gdyis_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 gdyinstanceof
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: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.źródło
is_a
nieaktualny?$class = 'Foo'; var_dump($obj instanceof $class);
is_a
vsinstanceof
operator jest to, żeis_a
akceptuje wyrażenia dla drugiego parametru, podczas gdy instanceof nie będzie. Na przykładis_a($object, 'Prefix_'.$name)
działa, podczas gdy$object instanceof 'Prefix_'.$name
nie działais_a
nigdy nie powinien był być przestarzały. Jednak teraz jest trochę za późno, aby to naprawić. Problem polega na tym, żeinstanceof
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 :
Źródło testu jest tutaj .
źródło
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 :
wyjścia:
źródło
is_a
działa z interfejsami w taki sam sposób, jakinstanceof
(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 vsis_a()
. Na przykład dlainstanceof
ciebie zrobiłbyś:vs następujące dla
is_a()
:lub
Edytuj Wygląda na to, że ChrisF usunął swoją odpowiedź, ale pierwsza część mojej odpowiedzi nadal obowiązuje.
źródło
Oprócz prędkości, inną ważną różnicą jest sposób, w jaki obsługują przypadki krawędzi.
Zatem is_a () podkreśla możliwe błędy, a instanceof je eliminuje.
źródło
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
jest krótszy niż
(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:
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.
jest bardziej czytelny niż:
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
źródło
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ę strukturainstanceof
lepiej (myślę, że jest ładniejsza) i nadal będę jej używać tam, gdzie mogę.źródło
Oto wyniki wydajności uzyskane stąd :
instanceof
jest szybszy.Funkcje
Razy (uruchom 5000 razy każdy)
źródło
Istnieje scenariusz, w którym
is_a()
działa tylko iinstanceof
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:
Jest to oparte na PHP 7.2.14.
źródło