PHP 5.3 引入的晚期靜態綁定(Late Static Bindings,簡稱 LSB)是一項重要特性,它解決了靜態方法在繼承體系中「綁定過早」的問題。簡單來說,LSB 允許在執行階段才決定調用哪個類的靜態方法或屬性,而非在定義階段就綁死在父類上。
在 PHP 5.3 之前,若在父類的靜態方法中使用 self:: 調用另一個靜態方法,即使子類覆寫了該方法,調用的依然是父類版本。請看下例:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who(); // 這裡綁定在 A 類
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test(); // 輸出:A(而非預期的 B)
?>
這是因為 self:: 在編譯時就解析為定義它的類(此處為 A),不具備多態性。
PHP 5.3 引入 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
?>
此時 static::who() 會在執行時解析為 B::who(),實現了真正的多態行為。
| 關鍵字 | 綁定時機 | 適用場景 |
|---|---|---|
self:: | 編譯期(定義類) | 確定不會被覆寫的內部方法、常數 |
static:: | 執行期(調用類) | 需要子類覆寫並多態調用的靜態方法 |
$this-> | 執行期(實例) | 非靜態上下文 |
配合 get_called_class() 函數,可在靜態上下文中獲取實際調用的類名:
<?php
class Base {
public static function factory() {
$class = get_called_class();
return new $class();
}
}
class Child extends Base {}
$obj = Child::factory(); // $obj 為 Child 實例
echo get_class($obj); // Child
?>
static::。self::(如私有輔助方法、類常數)。$this 或實例屬性,這會導致錯誤。晚期靜態綁定修補了 PHP 靜態成員在繼承體系中的多態缺失,使靜態工廠模式、Active Record 等設計模式的實現更加自然。升級至 PHP 5.3+ 專案時,建議審視現有 self:: 用法,視情況遷移至 static::。