PHP 5.3.0 以降、PHP には遅延静的バインディングと呼ばれる機能が追加されました。これは、継承スコープ内で静的に呼び出されるクラスを参照するために使用されます。
正確に言うと、遅延静的バインディングの動作原理は、前の「非転送呼び出し」にクラス名を保存することです。静的メソッド呼び出しを行う場合、クラス名は明示的に指定されたもの (通常は :: 演算子の左側) であり、非静的メソッド呼び出しを行う場合は、オブジェクトが属するクラスです。いわゆる「転送呼び出し」とは、self::、parent::、static::、および forward_static_call() の方法で行われる静的呼び出しを指します。 get_called_class() 関数を使用すると、呼び出されたメソッドのクラス名を取得でき、static:: はそのスコープを示します。
この機能は、言語内部の観点から「遅延静的バインディング」と呼ばれています。 「遅延バインディング」とは、static:: が現在のメソッドが定義されているクラスに解析されず、実際の実行時に計算されることを意味します。静的メソッドの呼び出し (ただし、それに限定されない) に使用できるため、「静的バインディング」とも呼ばれます。
Self:: 制限事項
現在のメソッドが定義されているクラスに応じて、現在のクラスへの静的参照には self:: または __CLASS__ を使用します:
例 #1 self:: 使用法
<?php class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); ?>
上記のルーチン
A
後期静的バインディングの使用法
後期静的バインディングは、実行時に最初に呼び出されるクラスを表す新しいキーワードを導入することで制限を回避することを目的としていました。簡単に言うと、このキーワードを使用すると、上記の例で test() を呼び出すときに、クラス A の代わりにクラス B を参照できるようになります。最終的には、新しいキーワードを導入せず、すでに予約されている静的キーワードを使用することが決定されました。
例 #2 static:: 簡単な使用法
<?php class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // 后期静态绑定从这里开始 } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); ?>
上記のルーチンは次の出力を行います:
B
注:
非静的環境では、呼び出されたクラスはオブジェクト インスタンスが属するクラスです。 $this-> は同じスコープ内のプライベート メソッドを呼び出そうとするため、static:: は異なる結果を返す可能性があります。もう 1 つの違いは、static:: は静的プロパティでのみ使用できることです。
例 #3 非静的環境で static::
<?php class A { private function foo() { echo "success!\n"; } public function test() { $this->foo(); static::foo(); } } class B extends A { /* foo() will be copied to B, hence its scope will still be A and * the call be successful */ } class C extends A { private function foo() { /* original method is replaced; the scope of the new one is C */ } } $b = new B(); $b->test(); $c = new C(); $c->test(); //fails ?>
を使用する場合、上記のルーチンは次のように出力します:
success! success! success! Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
注:
後の静的バインディングの分析は、完全に解決された静的呼び出しが取得されるまで続行されます。一方、parent:: または self:: を使用して静的呼び出しが行われた場合、呼び出し情報が転送されます。
例 #4 通話の転送と非転送
<?php class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__."\n"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); } public static function who() { echo __CLASS__."\n"; } } class C extends B { public static function who() { echo __CLASS__."\n"; } } C::test(); ?>
上記のルーチンは出力します:
A C C