まず、コードの一部を通じて遅延静的バインディングの概念を紹介します:
class A { public static function who() { echo __CLASS__, PHP_EOL; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__, PHP_EOL; } } B::test(); // A
このコードでは、self キーワードを使用しています。クラス B を使用して静的メソッド test() を呼び出すとき、self はクラス A の who() メソッドを指すため、出力は A になります。興奮しないでください。これは通常の静的バインディングです。 self キーワードが何を呼び出すかは、それが定義されているクラスによって異なります。つまり、継承方法や test() メソッドの呼び出しにどのサブクラスが使用されたかに関係なく、self キーワードはクラス A の who() メソッドを呼び出します。
遅延静的バインディングについてはどうですか?実際、これはインスタンス化されたクラス オブジェクトに似ており、インスタンス化された各オブジェクトは、親クラスの属性メソッドではなく、それ自体を呼び出します。通常の静的呼び出しはこのようにはなりませんが、実際にはインスタンス化されたオブジェクトと同じように静的プロパティ メソッドを呼び出す必要があるため、このとき static キーワードを使用して遅延静的バインディングを実装できます。
class C { public static function who() { echo __CLASS__, PHP_EOL; } public static function test() { static::who(); } } class D extends C { public static function who() { echo __CLASS__, PHP_EOL; } } D::test(); // D
static キーワードが使用されている場合、ここでクラス D によって呼び出される test() メソッド内で呼び出される who() はクラス D 自体です。
公式ドキュメントの定義は次のとおりです。
静的メソッド呼び出しを行う場合、クラス名は明示的に指定されたものです (通常は :: の左側にあります)。演算子); 非静的メソッド呼び出しが行われるとき、それはオブジェクトが属するクラスです。
この機能は、言語内部の観点から「遅延静的バインディング」と呼ばれています。 「遅延バインディング」とは、static:: が現在のメソッドが定義されているクラスに解決されず、実際の実行時に計算されることを意味します。静的メソッドの呼び出し (ただし、それに限定されない) に使用できるため、「静的バインディング」とも呼ばれます。
self キーワードと static キーワードに加えて、parent キーワードもあります。このキーワードの意味は明らかで、親クラスの静的コンテンツを呼び出します。テストには 3 つのキーワードを同時に使用します:
class E { public static function who() { echo __CLASS__, PHP_EOL; } public static function test() { self::who(); static::who(); } } class F extends E { public static function who() { echo __CLASS__, PHP_EOL; } } class G extends F { public static function who() { parent::who(); echo __CLASS__, PHP_EOL; } } G::test(); // E // F // G
最後に、2 つの PHP メソッドを見てみましょう。1 つは、現在呼び出されているクラスを取得するために使用される get_called_class() メソッドです。静的メソッドでは、他のビジネス ロジック操作を実行するための呼び出しメソッドに基づいて、現在のクラスがどのクラスであるかを判断できます。もう 1 つは、forward_static_call() メソッドで、静的メソッドの呼び出しに使用されます。
class H { public static function who() { echo __CLASS__ . ':' . join(',', func_get_args()), PHP_EOL; } public static function test() { echo get_called_class(), PHP_EOL; forward_static_call('who', 'a', 'b'); // xxx:a,b forward_static_call(['I', 'who'], 'c', 'd'); // I:c,d forward_static_call_array(['H', 'who'], ['e', 'f']); // H:e,f } } class I extends H { public static function who() { echo __CLASS__ . ':' . join(',', func_get_args()), PHP_EOL; } } function who() { echo 'xxx:' . join(',', func_get_args()), PHP_EOL; } H::test(); // H // xxx:a,b // I:c,d // H:e,f I::test(); // I // xxx:a,b // I:c,d // H:e,f
forward_static_call() でクラス名が指定されていない場合は、グローバル メソッドが呼び出されることに注意してください。 forward_static_call_array() は配列を使用してパラメータを渡します。
えええええ