sınıf içinde statik bir yöntem çağırmak?


166

aynı sınıf içindeki başka bir yöntemden statik yöntemi nasıl çağırabilirim?

$this->staticMethod();

veya

$this::staticMethod();

13
Bu ( selfvs $this) ilginizi çekebilir : stackoverflow.com/questions/151969/php-self-vs-this
Felix Kling

Sadece bir FYI, ilk örneğiniz, statik yöntemi sınıfın bir parçası olduğu ve bir örnek değişkeni üzerinden erişilemediğinden, statik yöntemi çağıran bir örnek değişkendir.
joejoeson

$ 'ı şimdi silebilirsiniz, lütfen yalnızca statik yöntemler kullanılıyorsa ve örnek yoksa işe yaramaz.
malhal

Yanıtlar:


322

...ama neden? $ this-> staticMethod () da çalışır. Self :: staticMethod () neden daha doğru (açıksa) açıklayabilir misiniz?
Ian Dunn

29
@Ian Dunn Basitçe söylemek $thisgerekirse , sadece bir nesne somutlaştırılmışsa ve sadece $this->methodmevcut bir nesnenin içinden kullanabilirsiniz . Nesneniz yoksa, yalnızca statik bir yöntemi çağırırsanız ve bu yöntemde aynı sınıfta başka bir statik yöntemi çağırmak istiyorsanız, kullanmanız gerekir self::. Bu nedenle, olası hataları (ve katı uyarıları) önlemek için kullanmak daha iyidir self.
jeroen

1
Teşekkürler! Laravel'de, yanlışlıkla kullanarak genişletilmiş bir denetleyici üzerinden statik yöntemi çağırdığını $this, ancak kod itti kadar sorun yoktu yüzey bulundu stage. hiçbir hata geri gelmedi, değer sadece 0. Bu, kullanım dikkatli olunself::
blamb

44

Bunun sınıfınız olduğunu varsayalım:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

    public static function staticMethod() { echo "static method\n"; }
}

foo()Yöntemin içinden, farklı seçeneklere bakalım:

$this->staticMethod();

Yani bu staticMethod()bir örnek yöntemi olarak çağırıyor , değil mi? O değil. Bunun nedeni, yöntemin public staticyorumlayıcı statik yöntem olarak adlandırılacağı için bildirilmesidir , bu nedenle beklendiği gibi çalışır. Bunu yapmanın, statik bir yöntem çağrısının gerçekleştiğini koddan daha az belirgin hale getirdiği iddia edilebilir.

$this::staticMethod();

PHP 5.3'ten beri $var::method()demek için kullanabilirsiniz <class-of-$var>::; Yukarıdaki kullanım durumu hala alışılmadık olsa da, bu oldukça uygundur. Bu bizi statik bir yöntem olarak adlandırmanın en yaygın yoluna getiriyor:

self::staticMethod();

Bunu düşünmeye başlamadan önce Şimdi, ::bir statik çağrısı operatörü, sana başka bir örnek verelim:

self::bar();

Bu yazdırılacaktır baz = 1, yani bu $this->bar()ve self::bar()aynı şeyi yapın; çünkü ::sadece bir kapsam çözümleme operatörüdür. Orada yapmak için var parent::, self::ve static::iş ve statik değişkenlere erişim sağlar; bir yöntemin nasıl çağrıldığı onun imzasına ve arayanın nasıl çağrıldığına bağlıdır.

Tüm bunları çalışırken görmek için bu 3v4l.org çıktısına bakın .


self::bar()yanıltıcı görünüyor - bu artık onaylanmadı mı? ( self::statik bir yöntem yerine bir örnek yöntemini çağırmak için kullanma ).
ToolmakerSteve

@ToolmakerSteve yanıltıcı olduğunu ne şekilde söylerdiniz?
Ja͢ck

Mantıken konuşursak, selfstatik bir yöntem çağrıldığında hiçbir şey yoktur . Tanım olarak: statik yöntem her yerden çağrılabilir ve bir "self" parametresi almaz. Yine de, phpsözdiziminin rahatlığını görüyorum , böylece yazmak zorunda kalmıyorsunuz MyClassName::. Statik olarak yazılan dillere alışkınım, burada derleyiciye geçerli kapsamdaki tüm değişkenler verilmelidir, böylece (eşdeğeri) self::atlanabilir. Böylece biri sadece self instanceMethod; söylemeye gerek yok self staticMethod.
ToolmakerSteve

15

Bu çok geç bir yanıttır, ancak önceki cevaplara biraz ayrıntı ekler

PHP'de statik yöntemleri aynı sınıftaki başka bir statik yöntemden çağırmak söz konusu olduğunda self, sınıf adı ile sınıf adı arasında ayrım yapmak önemlidir .

Örneğin bu kodu ele alalım:

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

Bu kodun çıktısı:

Orijinal sınıf

Genişletilmiş sınıf

Bunun nedeni self, çağrıldığı kodun sınıfı yerine kodun bulunduğu sınıfa başvurmasıdır.

Orijinal sınıfı devralan bir sınıfta tanımlanan bir yöntemi kullanmak istiyorsanız, aşağıdakine benzer bir şey kullanmanız gerekir:

$class = get_called_class();
$class::function_name(); 

2
Bunu bilgilendirici buldum. Küçük bir nit, diğer cevapların "yanıltıcı" olduğunu söyleyemem. "Eksik" olduklarını söylemek daha doğru; self::statik bir yöntem A'nın başka bir statik yöntem B'yi çağırdığı ve bir alt sınıfta B geçersiz kılındığı (nadir) durumda ne olduğu sorusunu (sorulmamış) ele almazlar . IMHO, "geçersiz" yöntemleri geçersiz kılma yöntemini kısıtlamak daha az kafa karıştırıcı; bu yeteneği statik düzeyde az miktarda kullanın. Başka bir deyişle, kodunuzun okuyucuları, örnek yöntemlerin (yani OO kodlamasının özüdür) yöntemi geçersiz kılmayı bekler, ancak statik olanları beklemez.
ToolmakerSteve

1
Çok yararlı ve sınıfın bir uzantısı orijinal sınıf değildir. Bu nedenle self, bu durumda kullanılmayacağı gerekçesidir . Birinci sınıfa ek olarak ayrı bir sınıf beyan ettiniz. selfGenişletilmiş sınıf içinde kullanmak , genişletilmiş sınıfa işaret eder. Bu diğer cevaplarla çelişmez, ama kesinlikle kapsamını göstermeye yardımcı olur self.
iyrin

2

Daha sonraki PHP sürümünde self::staticMethod();de çalışmaz. Sıkı standart hatayı atar.

Bu durumda, aynı sınıftan nesne oluşturabilir ve nesneye göre çağrı yapabiliriz

işte örnek

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

Sen olabilir eğer olsa bunu fun1yararlanarak değildir self, bunun bir örnek yöntemi yapmak mantıklı değil. Php Bunu yapmanın en uygun yolu beyan etmektir public static function fun1ardından sınıfını belirterek çağrı: Foo::fun1. Bu katı standart hatayı düzeltmenin amaçlanan yolu olduğundan eminim.
ToolmakerSteve
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.