「延遲靜態綑綁」(late static binding)一直是 PHP 社群的熱門討論話題,隨著 PHP 5.3 得來臨,這項功能終於得以實現。究竟何謂「延遲靜態綑綁」?它有甚麼用處?Sean Coates 在她的網誌提供了一個範例說明這種技術,並介紹它的實際用途。
簡單來說,「延遲靜態綑綁」就是把本來在編譯階段固定下來的表達式或變量,改成在執行階段才決定,當一個子類繼承了父類的「靜態綑綁」表達式,它的值便不能改變,很多情況下這未必是開發人員所希望見到的。這個構思已經討論了超過兩年,到了 PHP 5.3 我們終於可以見到它。
我們首先看看以下的範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Beer {
const NAME = 'Beer!';
public function getName() {
return self::NAME;
}
}
class Ale extends Beer {
const NAME = 'Ale!';
}
$beerDrink = new Beer;
$aleDrink = new Ale;
echo "Beer is: " . $beerDrink->getName() ."\n";
echo "Ale is: " . $aleDrink->getName() ."\n";
|
執行的結果是:
1
2
| Beer is: Beer!
Ale is: Beer!
|
這裏 Ale 繼承了 Beer 的函式 getName(),由於 self::NAME 在編譯階段已經運算成 Beer! 並固定下來,Ale 也一拼繼承了 getName() 的傳回值 Beer!,這似乎不是開發人員所願見到的。這種情況在 PHP 5.3 不會改變,幸好 Zend 加入了一種新語法解決這個問題,就是使用 static 這個關鍵字,以下的原碼把本來的 self::NAME 改成 static::NAME:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Beer {
const NAME = 'Beer!';
public function getName() {
return static::NAME;
}
}
class Ale extends Beer {
const NAME = 'Ale!';
}
$beerDrink = new Beer;
$aleDrink = new Ale;
echo "Beer is: " . $beerDrink->getName() ."\n";
echo "Ale is: " . $aleDrink->getName() ."\n";
|
結果將會是:
1
2
| Beer is: Beer!
Ale is: Ale!
|
新引入的 static:: 告訴編譯器無須在編譯階段把 static::NAME 運算出來,而是把整個表達式編譯成操作碼(opcode),讓 Zend Engine 在執行階段才運算它的值。