ホームページ  >  記事  >  バックエンド開発  >  phpの遅延静的バインディング

phpの遅延静的バインディング

伊谢尔伦
伊谢尔伦オリジナル
2016-11-23 13:51:27981ブラウズ

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 &#39;A&#39; 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


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。