1. 程式人生 > >PHP的後期靜態繫結

PHP的後期靜態繫結

參考:https://blog.csdn.net/lamp_yang_3533/article/details/79912453

1.定義

後期靜態繫結(也叫延遲靜態繫結),可用於在繼承範圍內引用靜態呼叫的類

2.工作原理

static 後期靜態繫結的工作原理是儲存了上一個非轉發呼叫(non-forwarding call)的類名
  • 當進行靜態方法呼叫時,該類名(static指向的類名)為明確指定的那個(通常是 :: 運算子的左側部分),即實際呼叫時的類。
  • 當進行非靜態方法呼叫時,即為該物件所屬的類。
  • "後期繫結"的意思是說,static:: 不再被解析為定義當前方法所在的類,而是在實際執行時計算的。

3.轉發呼叫

所謂的轉發呼叫(forwarding call)指的是通過以下幾種方式進行的靜態呼叫:self::parent::static:: 以及 forward_static_call() 。

可用 get_called_class() 函式被呼叫的方法所在的類名。

 4.非轉發呼叫

通過具體的類名或具體的物件進行的呼叫都是非轉發呼叫,即非上面四種方式的呼叫都是非轉發呼叫。

5.非靜態環境下$this和static呼叫的區別

①$this 會優先尋找所在定義範圍(父類)中的私有方法,如果存在就呼叫。
②static 是先到它指向的類(子類
)中尋找私有方法,如果找到了就會報錯,因為私有方法只能在它所定義的類內部呼叫;如果沒找到,再去所在定義範圍(父類)中尋找該私有方法,如果存在就呼叫。
<?php
 class  A  {
    private function  foo () {
        var_dump($this); echo '--';
        var_dump(new static); echo '--';
 
        echo __CLASS__; echo '--';
        echo get_called_class();
        echo
'<br>'; } public function test () { $this -> foo (); static:: foo (); echo '<br>'; } } class B extends A { } class C extends A { private function foo () { echo 'this is C'; } } (new B())->test(); (new C())->test(); ?> //輸出結果 object(B)#1 (0) { } --object(B)#2 (0) { } --A--B object(B)#1 (0) { } --object(B)#2 (0) { } --A--B object(C)#1 (0) { } --object(C)#2 (0) { } --A--C Fatal error: Uncaught Error: Call to private method C::foo() from context 'A' in /usercode/file.php:14 Stack trace: #0 /usercode/file.php(28): A->test() #1 {main} thrown in /usercode/file.php on line 14
非靜態環境下$this和static呼叫區別

6.後期靜態繫結解析

後期靜態繫結的解析會一直到取得一個完全解析了的靜態呼叫為止。如果靜態呼叫使用了 parent:: 或者 self:: 等轉發呼叫的形式,將會轉發呼叫資訊。
<?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 ();
        static::foo();
        forward_static_call(['A', 'foo']);
        echo '<br>';
    }
 
    public static function  who () {
        echo  __CLASS__ . "\n" ;
    }
}
 
class  C  extends  B  {
    public static function  who () {
        echo  __CLASS__ . "\n" ;
    }
 
    public static function test2() {
        self::test();
    }
}
 
class  D  extends  C  {
    public static function  who () {
        echo  __CLASS__ . "\n" ;
    }
}
 
B::foo();
B::test();
 
C::foo();
C::test();
 
D::foo();
D::test2();
?>

//輸出結果
B A B B B B 
C A C C C C 
D A D D D D 
後期靜態繫結