それは長くて悲しい話です。
PHP 5.2でこの警告が初めて導入されたとき、遅延静的バインディングはまだ言語に含まれていませんでした。遅い静的バインディングに慣れていない場合は、次のようなコードは期待どおりに機能しないことに注意してください。
<?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();
厳格モードの警告は別として、上記のコードは機能しません。のメソッドとして呼び出された場合でも、self::bar()
呼び出しはfoo()
明示的にのbar()
メソッドを参照します。ストリクトモードをオフにしてこのコードを実行しようとすると、「PHPの致命的なエラー:抽象メソッドParentClass :: bar()を呼び出せません」が表示されます。ParentClass
foo()
ChildClass
このため、PHP 5.2の抽象静的メソッドは役に立たなかった。全体のポイントとし、別の子クラスの異なる実装を提供-抽象メソッドを使用するのは、あなたがそれを呼び出すことになるだろうどのような実装を知らなくてもメソッドを呼び出すコードを書くことができるということです。しかし、PHP 5.2では、親クラスのメソッドを、それが呼び出された子クラスの静的メソッドを呼び出すための明確な方法を提供していないため、この抽象静的メソッドを使用することはできません。したがってabstract static
、PHP 5.2でのの使用はすべて、不適切なコードであり、おそらくself
キーワードの機能の誤解に影響を受けています。これについて警告を投げることは完全に合理的でした。
しかし、その後、PHP 5.3が追加され、static
キーワードを介してメソッドが呼び出されたクラスを参照する機能が追加されました(self
常に、メソッドが定義されたクラスを参照するキーワードとは異なります)。上記の例でに変更self::bar()
するstatic::bar()
と、PHP 5.3以降で問題なく機能します。あなたは、詳細について読むことができるself
対static
で新しい静的対新しい自己。
staticキーワードが追加されたためabstract static
、警告をスローしたという明確な議論はなくなりました。遅延静的バインディングの主な目的は、親クラスで定義されたメソッドが、子クラスで定義される静的メソッドを呼び出せるようにすることでした。遅い静的バインディングが存在することを考えると、抽象静的メソッドを許可することは合理的で一貫しているように見えます。
あなたはまだ、警告を維持するための主張をすることができると思います。たとえば、PHPでは抽象クラスの静的メソッドを呼び出すことができるため、上記の例では(で置き換えself
て修正した後でもstatic
)壊れているパブリックメソッドParentClass::foo()
を公開していて、本当に公開します。非静的クラスを使用すると、つまり、すべてのメソッドをインスタンスメソッドにして、すべての子をシングルトンか何かにすることで、この問題を解決できます。呼ばれる。この議論は弱いと思います(ParentClass
ParentClass
ParentClass::foo()
これは大したことではなく、静的クラスの代わりにシングルトンを使用することは、多くの場合、不必要に冗長で醜いです)が、あなたは合理的に同意しないかもしれません-それはやや主観的な呼び出しです。
それで、この議論に基づいて、PHP開発者は言語で警告を続けましたね?
ええと、正確ではありません。
上記のリンクのPHPバグレポート53081は、static::foo()
構造の追加により抽象静的メソッドが合理的かつ有用になったため、警告を削除するように求めていました。Rasmus Lerdorf(PHPの作成者)は、リクエストを偽のラベルとしてラベル付けすることから始め、警告を正当化するために長い推論の長い連鎖を通過します。次に、最後にこの交換が行われます。
ジョルジョ
知ってるけど:
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();
ラスムス
そう、それはまさにそれが働くべきである方法です。
ジョルジョ
しかし、それは許可されていません:(
ラスムス
何が許可されていませんか?
abstract class cA {
static function A(){static::B();}
abstract static function B();
}
class cB extends cA {
static function B(){echo "ok";}
}
cB::A();
これは正常に動作します。明らかにself :: B()を呼び出すことはできませんが、static :: B()で十分です。
彼の例のコードが「正常に機能する」というラスムスの主張は誤りです。ご存知のように、それは厳格なモード警告をスローします。strictモードをオンにせずにテストしていたと思います。とにかく、混乱したラスムスはリクエストを誤って「偽物」として閉じたままにしました。
そしてそれが警告がまだ言語である理由です。これは完全に満足できる説明ではないかもしれません-あなたはおそらく警告の正当な正当化があったことを望んでここに来ました。残念ながら、現実の世界では、合理的な意思決定からではなく、ありふれた過ちや悪い推論から選択が生まれることがあります。これは単にそれらの時代の1つです。
幸運なことに、推定可能なNikita Popovは、PHP RFCの一部としてPHP 7の言語から警告を削除しました:E_STRICT通知の再分類。結局のところ、正気が広まり、PHP 7がリリースされるとabstract static
、このばかげた警告を受け取らなくても、誰でも楽しく使用できます。