PHP'de self :: $ bar ile static :: $ bar arasındaki fark nedir?


125

Aşağıdaki örnekte kullanmak selfve kullanmak arasındaki fark nedir static?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

üretir

1234
1234

2
@deceze: Bu benzer bir soru, ancak yinelenen değil. Bu, anahtar kelimeleri özelliklerle birlikte kullanmayı sorarken, bunları yapıcılarla kullanmayı sorar.
BoltClock

Yanıtlar:


191

Bir selfsınıf üyesine başvurmak için kullandığınızda, anahtar kelimeyi içinde kullandığınız sınıfa atıfta bulunuyorsunuz. Bu durumda, Foosınıfınız adı verilen korumalı bir statik özelliği tanımlar $bar. Eğer kullandığınız zaman selfiçinde Fooözelliği başvurmak sınıfta, aynı sınıf durumdayız.

Bu nedenle self::$bar, Foosınıfınızda başka bir yerde kullanmayı denediyseniz, ancak Barmülk için farklı bir değere sahip bir sınıfınız varsa , bunun Foo::$baryerine onu kullanırdı Bar::$bar, ki bu sizin niyet ettiğiniz şey olmayabilir:

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

Ne zaman çağrı yoluyla bir yöntem static, sen adlandırılan bir özellik yürütmesini ediyoruz geç statik bağlamaları (PHP 5.3 tanıtıldı).

Yukarıdaki senaryoda, kullanmak (1234) ile selfsonuçlanacaktır Foo::$bar. Ve kullanmak (4321) ile staticsonuçlanacaktır Bar::$barçünkü ile staticyorumlayıcı, Barçalışma zamanı sırasında sınıf içindeki yeniden bildirimi hesaba katar .

Alt sınıflarda özellikleri genellikle yeniden bildirmediğiniz için genellikle yöntemler için veya hatta sınıfın kendisi için özellikler yerine geç statik bağlamaları kullanırsınız; staticGeç bağlanmış bir kurucuyu çağırmak için anahtar sözcüğün kullanımına bir örnek şu ilgili soruda bulunabilir: Yeni benlik ve yeni statik

Bununla birlikte, bu staticözelliklerle birlikte kullanılmasını da engellemez .


Alt sınıfta kolaylıkla yeniden beyan edebilirsiniz, ana sınıf, alt sınıfın yeniden beyan etmedikçe kullandığı varsayılan bir değer olabilir. Ebeveyn sınıfındaysanız, sanırım self :: kullanmak güvenlidir ve eğer bir çocuk sınıfındaysa, ikisinden birini kullanmak için bir argüman bulabilirsin, ancak self :: eğer beklemiyorsan da işe yarayacaktır. hiç yeniden beyan et.
Andrew

3
phpfiddle.org'a gidin ve bunu çalıştırın<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
Yevgeniy Afanasyev

2
İlk iki paragraf ifadesi kafa karıştırıcıdır, belirsiz bir zamire sahiptir, "o" ve ayrıca daha sonraki paragraflar aynı bilgiyi daha açık bir şekilde açıkladığından gereksizdir. İlk iki paragrafı en üstte "Yukarıdaki senaryoda" ile başlayan sonraki paragrafla değiştirmenizi öneririm. Bu şekilde, en alt satırda, kovalamaca-kesik yanıt en üsttedir. Anlaşılır ve takibi kolaydır.
ahnbizcad

Bunu düşünmenin başka bir yolu: self::$abcİçeride kullanıldığında class Foosöylemekle aynı şey Foo::$abc. $abcBir alt sınıftaki herhangi bir yeniden bildirimden etkilenmez . AFAIK, kullanmanın tek nedeni self, sınıf adını kullanmaktan kaçınmak için bir kısaltmadır Foo, bu daha uzun olabilir. [Bu aynı zamanda sınıf adını tüm bu yerleri değiştirmeden değiştirebileceğiniz anlamına gelir - ancak bu, IMHO'nun pek bir nedeni değildir.] (PHP'nin isim seçimi talihsizdir ve geriye doğru görünür; "statik" değişebilecek olanıdır - ki doğal dilde kullanılan "statik" kelimesinin konuşma anlamının tam tersidir.)
ToolmakerSteve

4

Belirtildiği gibi, ana farklılıklardan biri, staticgeç statik bağlamalara izin vermesidir. Bulduğum en kullanışlı senaryolardan biri, Singleton Sınıfları için Base sınıfları oluşturmaktı:

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

return static::$nameBase sınıfında kullanmak , uzatıldığında statik olarak eklenmiş olanı döndürür. Kullanmak için olsaydı return self::$nameo zaman B::getName()o Taban sınıfta bildirilen ne olduğu gibi boş bir dize dönecekti.


1

İle selfçağrı:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return self::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "123"
echo (new Bar)->getVar();

Sence geçersiz halde, yukarıda görebilirsiniz $varbizim ile Barsınıfının, hala getiri 123biz açıkça için PHP istediler, çünkü selfsırayla sorar değişken, Fooyerine s değişkeni.

Şimdi aramayı ile değiştirirsek, staticbunun yerine Bars geçersiz kılınan değeri alacağız :

İle staticçağrı:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return static::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "234"
echo (new Bar)->getVar();
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.