首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP static 與 self 關鍵字深度解析:靜態綁定與繼承行為的關鍵差異

     編輯:PHP 相關知識

PHP static 與 self 關鍵字深度解析:靜態綁定與繼承行為的關鍵差異

static 關鍵字基礎特性

  • 靜態屬性/方法屬於類別而非實例,無需實例化即可存取(ClassName::$prop、ClassName::method())
  • 靜態屬性不能透過 $obj->prop 存取,但靜態方法可透過物件呼叫
  • 靜態方法內不可使用 $this,無法存取非靜態成員
  • 子類別繼承父類別靜態成員時,若未覆寫則共享同一記憶體位址

後期靜態綁定(Late Static Bindings,LSB)

PHP 5.3 引入 static:: 關鍵字,解決繼承體系中「誰在呼叫」的問題:

  • self:: 永遠解析為定義該方法的類別(編譯期綁定)
  • static:: 解析為實際呼叫的類別(執行期綁定)
  • get_called_class() 可取得實際被呼叫的類別名稱

實戰對比:self vs static

<?php
class Vehicle {
    protected static $name = 'This is a Vehicle';
    
    public static function what_vehicle() {
        echo get_called_class() . "\n"; // 顯示實際呼叫類別
        echo self::$name . "\n";        // 編譯期綁定:Vehicle
    }
}

class Sedan extends Vehicle {
    protected static $name = 'This is a Sedan';
}

Sedan::what_vehicle();
// 輸出:
// Sedan
// This is a Vehicle   ← self 綁定父類別
<?php
class Vehicle {
    protected static $name = 'This is a Vehicle';
    
    public static function what_vehicle() {
        echo get_called_class() . "\n";
        echo static::$name . "\n";      // 執行期綁定:Sedan
    }
}

class Sedan extends Vehicle {
    protected static $name = 'This is a Sedan';
}

Sedan::what_vehicle();
// 輸出:
// Sedan
// This is a Sedan     ← static 綁定子類別

應用場景:Active Record 基類

abstract class Model {
    protected static $table = '';
    
    public static function find($id) {
        // 使用 static:: 取得子類別定義的 table
        $table = static::$table;
        $class = get_called_class();
        // ... 執行查詢並回傳 $class 實例
    }
}

class User extends Model {
    protected static $table = 'users';
}

$user = User::find(1); // 正確使用 users 表

常見陷阱

  1. parent::、self::、static::、forward_static_call() 均屬「轉發呼叫」,不會更新 LSB 記錄的類別
  2. 靜態屬性若在子類別未重新宣告,static::$prop 仍指向父類別記憶體(共享值)
  3. self:: 適合呼叫不應被覆寫的內部實作細節;static:: 適合擴充點(如工廠方法、Active Record)

總結

理解 self(早期綁定)與 static(後期綁定)的差異,是掌握 PHP 物件導向繼承機制的關鍵。善用 LSB 能編寫出更彈性、可擴充的基類別架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved