İs_a ve instanceof arasındaki fark nedir?


205

Bunun instanceofbir operatör ve bunun is_abir yöntem olduğunun farkındayım .

Yöntem performansta daha yavaş mı? Ne kullanmayı tercih edersin?


15
is_a () daha yavaş olabilir - ancak call_user_func () kullanarak çağırabilirsiniz, ancak instanceof bu şekilde
çağrılamaz

Yanıtlar:


211

Güncelleme

İtibariyle PHP 5.3.9 , işlevselliği is_a()değişti. Aşağıdaki orijinal yanıt , ilk bağımsız değişken olarak bir kabul etmesi is_a() gerektiğini belirtir Object, ancak PHP sürümleri> = 5.3.9 , bunun yerine dize sınıfı adlarının karşılaştırılmasına izin vermek için isteğe bağlı bir üçüncü boole bağımsız değişkenini $allow_string(varsayılan olarak false) kabul eder :

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);

Arasında yeni davranış temel fark, instanceofve is_a()ki instanceof, oysa her zaman hedefi (uzanan sınıflar da dahil olmak üzere) belirtilen sınıfın bir örneği olup olmadığını kontrol edecek is_a(), yalnızca nesne örneği gerektirir $allow_stringbağımsız değişken varsayılan değerine ayarlanır false.


orijinal

Aslında is_abir işlev, instanceofbir dil yapısıdır. is_aönemli ölçüde daha yavaş olacaktır (bir işlev çağrısını yürütmenin tüm ek yüküne sahip olduğundan), ancak her iki yöntemde de genel yürütme süresi minimumdur.

Artık 5.3'ten beri kullanımdan kaldırılmıyor, bu yüzden endişelenmenize gerek yok.

Ancak bir fark var. is_abir işlev olması, bir nesneyi parametre 1 olarak ve bir dize (değişken, sabit veya değişmez) parametre 2 olarak alır.

is_a($object, $string); // <- Only way to call it

instanceof bir nesneyi parametre 1 olarak alır ve parametre adı olarak bir sınıf adı (değişken), nesne örneği (değişken) veya sınıf tanımlayıcısı (tırnak işaretleri olmadan yazılan sınıf adı) alabilir.

$object instanceof $string;      // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName;    // <- identifier for the class

36
Neden is_atarif edilmedi?
Theodore R. Smith

21
@ theodore-r-smith Belgelere göre "popüler istek tarafından tanımlanmadı" php.net/manual/en/migration53.undeprecated.php
Janci

3
@danip$class = 'Foo'; var_dump($obj instanceof $class);
ircmaxell

39
Operatöre is_akarşı dikkat edilmesi gereken bir diğer şey , ikinci parametre için ifadeleri kabul ederken, instanceof alışkanlıktır. Örnek için işler yaparken değilinstanceofis_ais_a($object, 'Prefix_'.$name)$object instanceof 'Prefix_'.$name
Evan Purkhiser

6
is_aasla ilk etapta reddedilmemeliydi. Gerçi şimdi düzeltmek için biraz geç. Sorun, instanceofoperatörün PHP 4'te sözdizimi hataları is_aatması ve operatörün tanıtılmasıyla aynı anda kullanımdan kaldırılmasından bu yana , etrafa bir E_STRICT atmadan hem PHP 4 hem de 5 için kod yazmak imkansız hale geldi. if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }PHP 4'te hala bir sözdizimi hatasına neden olacağından bile yapamazsınız
meustrus

47

İşte is_a () ve instanceof performans sonuçları :

Test name       Repeats         Result          Performance     
instanceof      10000           0.028343 sec    +0.00%
is_a()          10000           0.043927 sec    -54.98%

Test kaynağı burada .


6
Başka bir deyişle, fark sadece 10000 kullanım başına ~ 0.015 saniye kaydetmeniz gerekiyorsa önemlidir.
CJ Dennis

1
İtibariyle php 7hiçbir fark yoktur.
MAX

@CJDennis Deneyimle, herkes böyle düşündüğünde, nihai ürün beklenenden daha yavaş olacaktır. (Soft + OS + sunucuları optimize edilmemiştir). Eklenen sürenin her zaman doğrusal olmadığını, ancak üstel olabileceğini unutmayın. Her zaman performans göz önünde bulundurun.
Toto

@Toto Deneyimli geliştiricilerin yeni başlayanlardan öğrenebilecekleri hakkında mükemmel bir blog yazısı var. Umarım sağ üstte görebilirsiniz. Erken optimizasyona dikkat edin! Zamanlama problemlerini ancak problem olduktan sonra çözün ! Performans olduğu gibi kabul edilebilirse, değiştirmek için zaman harcamayın!
CJ Dennis

10

instanceofdiğer nesne örnekleri, sınıfın adı veya bir arabirim ile kullanılabilir. Ben sanmıyorum is_a()bu olursa beni arayüzlerle eserler (bir sınıf adı temsil eden tek bir dize), ancak düzeltin. (Güncelleme: Bkz. Https://gist.github.com/1455148 )

Php.net'ten bir örnek :

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'

çıktılar:

bool(true)
bool(true)
bool(false)

3
is_aarayüzlerle aynı şekilde çalışır instanceof(aynı şeyi söyleyecektim, ama göndermeden önce kontrol ettim ve gerçekten işe yarıyor) ...
ircmaxell

2
-1 lütfen bir özete bağlanmak yerine güncellemeyi özetleyin. Bu, öğrenmeye çalışan insanlar için yararsızdır.
Erick Robertson

5

ChrisF'in cevabı ile ilgili olarak, is_a() olarak, PHP 5.3.0'dan itibaren artık kullanımdan kaldırılmamıştır . Bunun gibi şeyler için resmi kaynağa gitmenin her zaman daha güvenli olduğunu düşünüyorum.

Sorunuzla ilgili olarak, Daniel, performans farklılıkları hakkında söyleyemem, ancak bir kısmı okunabilirliğe inecek ve daha kolay çalışabileceğinizi göreceksiniz.

Ayrıca, vs vs bir çek ihmal etrafında karışıklık hakkında bazı tartışmalar var . Örneğin, şunları yapabilirsiniz:instanceofis_a()instanceof

<?php
if( !($a instanceof A) ) { //... }
?>

vs aşağıdakiler için is_a():

<?php
if( !is_a($a, 'A' ) { //... }
?>

veya

<?php
if( is_a($a, 'A') === FALSE) { //... }
?>

Edit ChrisF cevabını silmiş gibi görünüyor, ancak cevabımın ilk kısmı hala duruyor.


5

Hızın yanı sıra, bir diğer önemli fark da kenar kasaları nasıl ele aldıklarıdır.

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.

Yani, is_a () olası hataları vurgularken instanceof bunları bastırır.


2

Optimizasyon minimaldir. Ve mikro-optimizasyonlar, kodun okunabilirliği, anlaşılabilirliği ve kararlılığı önünde asla gerçek bir cevap değildir.

(şahsen instanceof'i tercih ederim tercih , ama seçim senin;))

Temel fark, instanceof ile doğrudan sınıf adını kullanma olasılığıdır

$ bir sınıfım örneği

daha kısa

is_a ($ a, Sınıfım :: sınıf)

(tamam… önemsiz değil.)

İnstanceof (dil yapısı) ve is_a arasındaki sözdizimi rengi de benim için yararlıdır. daha büyük işlemlere renk fonksiyonu sağlar. Ve eğer tek kullanımlık olursa, daha fazla parantez gerektirmez.

Not: Elbette MyClass :: sınıfı yerine daha kısa bir doğrudan dize kullanabilirsiniz:

is_a ($ a, 'Sınıfım')

Ancak bir kodda doğrudan dize kullanmak iyi bir uygulama değildir .

Basit dize ve sınıf adları arasında bir fark yaratabiliyorsanız, sözdizimsel renklendirme daha iyi ve daha yararlıdır. Ayrıca, sabit sınıf adıyla adları değiştirmek daha kolaydır. Özellikle takma adla ad alanı kullanıyorsanız.

Peki, neden is_a () kullanıyorsunuz ?

Aynı neden için: okunabilirlik ve istenemezlik. (seçim sizin) Özel olarak kullanıldığında ! veya diğer boole operatörleri: is_a parantez ile daha pratik görünmektedir.

eğer ($ a AND (! is_a ($ a, Sınıfım :: sınıf) VEYA is_a ($ a, SınıfımClass :: sınıf)))

daha okunabilir:

if ($ a AND (! ($ $ bir Sınıfım örneği) VEYA ($ a intanceof MyOtherClass)))

Diğer bir iyi neden, işlevlerde geri aramayı kullanmanız gerektiğidir. ( dizi_map … gibi ) instanceof bir işlev değildir, bir dil yapısıdır, bu nedenle geri arama olarak kullanamazsınız.

Bu durumlarda, is_a yararlı olabilir


1

Performans için konuşamam - henüz hiçbir şey ölçmedim - ama ne yapmaya çalıştığınıza bağlı olarak, sınırlamalar var instanceof. Kısa bir süre önce bu konudaki soruma göz atın:

PHP 'instanceof' sınıf sabiti ile başarısız oluyor

Bunun is_ayerine kullandım. Ben instanceofdaha iyi yapısını seviyorum (Bence güzel okur) ve mümkün olduğunca kullanmaya devam edecektir.


1

İşte elde edilen performans sonuçları burada :

instanceof daha hızlı.

Fonksiyonlar

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';
}

Times (her biri 5000 kez çalıştırın)

0.00573397 // method_1(5) 
0.01437402 // method_2(5) 
0.00376201 // method_3(5)

1

Sadece is_a()çalışan ve instanceofbaşarısız olacak bir senaryo var .

instanceof değişmez bir sınıf adı veya bir nesne veya dize (bir sınıfın adı ile) olan bir değişkeni doğru argümanı olarak bekler.

Ancak bir işlev çağrısından bir sınıf adının dizesini sağlamak istiyorsanız, çalışmaz ve sözdizimi hatasına neden olur.

Ancak, aynı senaryo aşağıdakilerle uyumludur: is_a() .

Misal:

<?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()));

Bu PHP 7.2.14 tabanlıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.