Duruk İçselleştirim

PHP 5.3.0'dan itibaren, miras alınan duruk bağlamın çağrıldığı nesne bağlamında değerlendirilmesini sağlayan ve duruk içselleştirim (İng.: late static bindings) adı verilen bir özellik eklenmiştir.

Daha kesin olarak, duruk içselleştirim son "ötelenmeyen çağrıda" bahsi geçen sınıfın saklanmasıyla çalışır. Duruk yöntem çağrısı durumunda sınıfın adı açıkça (genellikle :: işlecinin sol tarafında) belirtilmiştir. Duruk olmayan yöntem çağrısı durumunda söz konusu sınıf, nesnenin sınıfıdır. Bir "ötelenen çağrı", bir self::, parent::, static:: yöntemi veya sınıf hiyerarşisi üzerinden gidiliyorsa forward_static_call() çağrısıdır. get_called_class() işlevi, çağrılan sınıfın ismini bir dize olarak almakta kullanılabilir ve bağlamını static:: belirler.

"Duruk içselleştirme", static:: yöntemin çalışma anında, tanımlandığı nesnenin bağlamında değil, çağrıldığı nesnenin bağlamında değerlendirilmesi olgusunu betimler.

self:: ile ilgili sınırlamalar

self:: veya __CLASS__ gibi bulunduğu sınıfa duruk gönderim yapan öğeler, örnekten de görüleceği üzere, yöntemi miras alan sınıf bağlamında değil, yöntemin ait olduğu sınıf bağlamında değerlendirilirler:

Örnek 1 - self:: kullanımı

<?php
class {
    public static function 
kimsin() {
        echo 
__CLASS__;
    }
    public static function 
dene() {
        
self::kimsin();
    }
}

class 
extends {
    public static function 
kimsin() {
        echo 
__CLASS__;
    }
}

B::dene();
?>

Yukarıdaki örneğin çıktısı:

A

Duruk İçselleştirimin uygulanması

Duruk içselleştirimde çözümlemenin, gönderimin çalışma anında ilk çağrıldığı sınıfla sınırlandırılması, gönderim için özel bir anahtar sözcük kullanılarak sağlanır. Temel olarak, böyle bir anahtar sözcük, yukarıdaki örnekteki dene() yönteminin aşağıdaki gibi B döndürmesini sağlar. Bunun için yeni bir anahtar sözcük atamaktansa, zaten bir anahtar sözcük olan static sözcüğü kullanılmıştır.

Örnek 2 - static:: kullanımı

<?php
class {
    public static function 
kimsin() {
        echo 
__CLASS__;
    }
    public static function 
dene() {
        static::
kimsin(); // Burada duruk içselleştirim yapılıyor
    
}
}

class 
extends {
    public static function 
kimsin() {
         echo 
__CLASS__;
    }
}

B::dene();
?>

Yukarıdaki örneğin çıktısı:

B

Bilginize:

Duruk olmayan bağlamlarda, çağrılan sınıf, nesne örneğini sınıfı olacaktır. $this-> aynı bağlamdaki private yöntemleri çağırmayı denerken, static:: kullanımı farklı sonuçlar verebilir. static:: ile ilgili diğer bir fark, sadece duruk özellikler için kullanılabilmesidir.

Örnek 3 - Duruk olmayan bağlamda static:: kullanımı

<?php
class {
    private function 
foo() {
        echo 
"success!\n";
    }

    public function 
dene() {
        
$this->foo();
        static::
foo();
    }
}

class 
extends {
   
/* foo() B'ye kopyalanacak, dolayısıyls bağlamı hala A olacak ve
    * çağrı başarılı olacaktır. */
}

class 
extends {
    private function 
foo() {
        
/* özgün yöntem değişti; yenisinin bağlamı C'dir */
    
}
}

$b = new B();
$b->test();
$c = new C();
$c->test();   //hata verir
?>

Yukarıdaki örneğin çıktısı:

success!
success!
success!


Fatal error:  Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

Bilginize:

Duruk içselleştirimin çözümlemesi duruk çağrının tamamen çözümlendiği noktada durdurulur, daha öteye gidilmez. Diğer taraftan, parent:: veya self:: gibi anahtar sözcükler kullanılarak yapılan duruk çağrılar çağrı bilgisini ötelerler.

Örnek 4 Ötelenen ve ötelenmeyen çağrılar

<?php
class {
    public static function 
nesin() {
        static::
kimsin();
    }

    public static function 
kimsin() {
        echo 
__CLASS__."\n";
    }
}

class 
extends {
    public static function 
dene() {
        
A::nesin();
        
parent::nesin();
        
self::nesin();
    }

    public static function 
kimsin() {
        echo 
__CLASS__."\n";
    }
}
class 
extends {
    public static function 
kimsin() {
        echo 
__CLASS__."\n";
    }
}

C::dene();
?>

Yukarıdaki örneğin çıktısı:

A
C
C