最近更新: 2009-11-22

PHP 5.3/6 新增功能 - Late Static Bindings

PHP5.3/6.0 新增延後靜態繫結(late static bindings)功能。 此功能由關鍵字 static 實現,係對照 self 之功能而出現。

self 關鍵字採用儘早靜態繫結策略,PHP 在解譯語法時,就直接將 self 繫結到它所在的類別。static 關鍵字採用延後靜態繫結(late static bindings)策略,要等到執行到那一段敘述時, PHP 才會根據調用者所屬類別來設定 static 所代表的類別。

Static 範例

在此例中,PHP 解譯時就設定 Class1 中的 self 等於 Class1 ,故將取出 Class1::$text 之值印出。 PHP 執行到 Class4::foo() 時,因為是透過 Class4 調用 foo() , 所以設定 Class3 中的 static 等於 Class4 。故將取出 Class4::$text 之值印出。

get_called_class() 是 PHP 5.3 新增的函數,配合此函數更容易看出 self 與 static 的差異。

<?php
class Class1 {
    // fullname: Class1::$text
    protected static $text = 'text in class1';
    public static function foo() {
        echo self::$text . ", " . get_called_class() . " called in\n";
    }
}

class Class2 extends Class1 {
    // fullname: Class2::$text
    protected static $text = 'text in class2';
}

Class2::foo();

class Class3 {
    // fullname: Class3::$text
    protected static $text = 'text in class3';
    public static function foo() {
        echo static::$text . ", " . get_called_class() . " called in\n";
    }
}

class Class4 extends Class3 {
    // fullname: Class4::$text
    protected static $text = 'text in class4';
}

Class4::foo();
?>

請注意第6行是用 self ;第21行則是用 static 。

text in class1, Class2 called in
text in class4, Class4 called in

這時要注意成員的存取屬性不可以是 private 。 在此例中,如果 Class4::$text 設為 private ,則 Class4::foo() 會擲出試圖存取其他類別私有成員的錯誤。 因為對 PHP 而言,它實際上是調用 Class3::foo() 去讀取 Class4::$text 之值,並不是同一個類別的成員互相存取。

forward_static_call()

配合 Late static bindings ,PHP 新增了 forward_static_call() / forward_static_call_array() 函數以補足 call_user_func() / call_user_func_array() 的不足。

forward_static_call() 只能在類別定義中使用,所以 PHP 可以根據它所在的類別,決定 static 將繫結到哪個類別上。 而 call_user_func() 可以在任何場所使用,它不帶有所屬類別的資訊,所以 PHP 無法動態繫結 static 所指涉的類別。 在此情形下, PHP 總是把 static 繫結到 call_user_func() 所調用的類別上。

<?php
class Class3 {
    // fullname: Class3::$text
    protected static $text = 'text in class3';
    public static function foo() {
        echo static::$text . ", " . get_called_class() . " called in\n";
    }
}

class Class5 extends Class3 {
    public static function callFoo() {
        forward_static_call(array('Class3', 'foo')); //Class5 called.
        call_user_func(array('Class3', 'foo')); //Class3 called.
    }
}

Class5::callFoo();
?>
text in class3, Class5 called in
text in class3, Class3 called in
相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/10796755.html