Uzun, üzücü bir hikaye.
PHP 5.2 bu uyarıyı ilk kez tanıttığında, geç statik bağlamalar henüz dilde değildi. Geç statik bağlamalara aşina değilseniz, bunun gibi bir kodun beklediğiniz gibi çalışmadığını unutmayın:
<?php
abstract class ParentClass {
static function foo() {
echo "I'm gonna do bar()";
self::bar();
}
abstract static function bar();
}
class ChildClass extends ParentClass {
static function bar() {
echo "Hello, World!";
}
}
ChildClass::foo();
Katı mod uyarısını bir kenara bırakırsak, yukarıdaki kod çalışmıyor. self::bar()
Çağrı foo()
açıkça atıfta bar()
yöntemi ParentClass
bile, foo()
bir yöntem olarak adlandırılır ChildClass
. Bu kodu katı mod kapalıyken çalıştırmayı denerseniz, " PHP Ölümcül hatası: Soyut yöntem ParentClass :: bar () çağrılamıyor " mesajını görürsünüz .
Bu göz önüne alındığında, PHP 5.2'deki soyut statik yöntemler işe yaramazdı. Tüm nokta ve daha sonra farklı çocuk sınıfları farklı uygulamaları sağlamak - soyut bir yöntemi kullanarak bunu çağırarak olacak neler uygulama bilmeden yöntemini çağıran bir kod yazabilirsiniz olmasıdır. Ancak PHP 5.2, çağrıldığı alt sınıfın statik bir yöntemini çağıran bir üst sınıfın bir yöntemini yazmak için temiz bir yol sunmadığından, soyut statik yöntemlerin bu şekilde kullanılması mümkün değildir. Dolayısıyla abstract static
, PHP 5.2'deki herhangi bir kullanım kötü koddur ve muhtemelen self
anahtar kelimenin nasıl çalıştığının yanlış anlaşılmasından esinlenmiştir . Bunun üzerine bir uyarıda bulunmak tamamen mantıklıydı.
Ancak daha sonra, bir yöntemin static
anahtar kelime aracılığıyla çağrıldığı sınıfa atıfta bulunma yeteneğine PHP 5.3 eklendi ( self
her zaman yöntemin tanımlandığı sınıfa atıfta bulunan anahtar sözcüğün aksine ). Eğer değiştirirseniz self::bar()
için static::bar()
yukarıdaki benim örnekte, PHP 5.3 ve üzeri cezası çalışır. New self vs. new static bölümünde self
vs hakkında daha fazla bilgi edinebilirsiniz .static
Statik anahtar kelime eklendiğinde, abstract static
bir uyarı vermenin açık argümanı ortadan kalktı. Geç statik bağlamaların ana amacı, bir üst sınıfta tanımlanan yöntemlerin alt sınıflarda tanımlanacak statik yöntemleri çağırmasına izin vermekti; soyut statik yöntemlere izin verilmesi, geç statik bağların varlığı göz önüne alındığında makul ve tutarlı görünmektedir.
Yine de, sanırım uyarıyı saklamak için bir dava açabilirsiniz. Örneğin, PHP soyut sınıfların statik yöntemlerini çağırmanıza izin verdiğinden, yukarıdaki örneğimde ( self
ile değiştirerek düzelttikten sonra bile static
) bozuk olan ve gerçekten yapmak istemediğiniz genel bir yöntemi ParentClass::foo()
ortaya koyduğunuzu iddia edebilirsiniz. maruz bırakmak. Statik olmayan bir sınıf kullanmak - yani, tüm yöntem örnek yöntemlerini yapmak ve hepsinin alt öğelerini tekil yapmak ya da başka bir şey yapmak - bu sorunu çözecektir, çünkü soyut olduğundan , örneklenemez ve bu nedenle örnek yöntemleri olamaz olarak adlandırılabilir. Bu argümanın zayıf olduğunu düşünüyorum (çünküParentClass
ParentClass
ParentClass::foo()
büyük bir sorun değildir ve statik sınıflar yerine tekil kullanmak çoğu zaman gereksiz bir şekilde ayrıntılı ve çirkindir), ancak makul bir şekilde katılmayabilirsiniz - bu biraz öznel bir çağrıdır.
Yani bu argümana dayanarak, PHP geliştiricileri uyarıyı dilde tuttu, değil mi?
Ah, tam olarak değil .
Yukarıda bağlantısı verilen 53081 numaralı PHP hata raporu, yapının eklenmesi static::foo()
soyut statik yöntemleri mantıklı ve kullanışlı hale getirdiğinden , uyarının kaldırılması çağrısında bulundu . Rasmus Lerdorf (PHP'nin yaratıcısı), isteği sahte olarak etiketleyerek işe başlar ve uyarıyı haklı çıkarmaya çalışmak için uzun bir kötü mantık zincirinden geçer. Sonunda, bu değişim gerçekleşir:
Giorgio
biliyorum ama:
abstract class cA
{
//static function A(){self::B();} error, undefined method
static function A(){static::B();} // good
abstract static function B();
}
class cB extends cA
{
static function B(){echo "ok";}
}
cB::A();
Rasmus
Doğru, tam olarak nasıl çalışması gerektiği bu.
Giorgio
ancak buna izin verilmiyor :(
Rasmus
Neye izin verilmiyor?
abstract class cA {
static function A(){static::B();}
abstract static function B();
}
class cB extends cA {
static function B(){echo "ok";}
}
cB::A();
Bu iyi çalışıyor. Belli ki self :: B () 'yi çağıramazsınız, ancak static :: B () iyidir.
Rasmus'un kendi örneğindeki kodun "iyi çalıştığı" iddiası yanlıştır; bildiğiniz gibi katı mod uyarısı veriyor. Sanırım katı mod açılmadan test ediyordu. Ne olursa olsun, kafası karışmış bir Rasmus, talebi yanlışlıkla "sahte" olarak kapattı.
Ve bu yüzden uyarı hala dilde. Bu tamamen tatmin edici bir açıklama olmayabilir - muhtemelen buraya uyarının rasyonel bir gerekçesi olduğunu umarak geldiniz. Ne yazık ki, gerçek dünyada bazen seçimler rasyonel karar vermekten ziyade sıradan hatalardan ve kötü muhakemeden doğar. Bu sadece o zamanlardan biridir.
Neyse ki, tahmin edilebilir Nikita Popov, PHP RFC'nin bir parçası olarak uyarıyı PHP 7'deki dilden kaldırdı : E_STRICT bildirimlerini yeniden sınıflandır . Sonuçta, akıl sağlığı üstün geldi ve PHP 7 piyasaya sürüldüğünde, abstract static
bu aptal uyarıyı almadan hepimiz mutlu bir şekilde kullanabiliriz .