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

PHP 5 虛擬函數機制:self vs $this 與靜態晚期靜態綁定

     編輯:PHP 綜合知識

核心概念

PHP 5 所有方法預設都是「虛擬」的(可被子類覆寫)。關鍵在於父類內部如何呼叫自身方法:

  • self::method():編譯期綁定,永遠呼叫當前類別定義的方法,不受子類覆寫影響。
  • $this->method():運行期綁定 (多態),實際呼叫實例真實類別的方法,子類覆寫生效。

實例演示

<?php
class A {
    public function x() { echo "A::x()\n"; }
    public function y() { self::x();  echo "A::y()\n"; } // 編譯期綁定
    public function z() { $this->x(); echo "A::z()\n"; } // 運行期綁定
}

class B extends A {
    public function x() { echo "B::x()\n"; } // 覆寫 x()
}

$b = new B();
$b->y(); // 輸出:A::x() → A::y()
echo "--\n";
$b->z(); // 輸出:B::x() → A::z()
?>

結果解析:y() 使用 self::x() 鎖死在 A,z() 使用 $this->x() 實現多態呼叫 B::x()。

靜態方法的晚期靜態綁定 (Late Static Binding, LSB)

PHP 5.3 引入 static:: 關鍵字,解決靜態方法繼承時的綁定問題:

<?php
class ParentClass {
    public static function say($str) {
        static::doPrint($str); // LSB:運行期解析為實際調用類別
    }
    public static function doPrint($str) {
        echo "<p>Parent says $str</p>\n";
    }
}

class ChildClass extends ParentClass {
    public static function doPrint($str) {
        echo "<p>Child says $str</p>\n";
    }
}

class AnotherChildClass extends ParentClass {
    public static function doPrint($str) {
        echo "<p>AnotherChild says $str</p>\n";
    }
}

ChildClass::say('Hello');        // Child says Hello
AnotherChildClass::say('Hello'); // AnotherChild says Hello
?>

self::doPrint() 永遠呼叫 ParentClass::doPrint();static::doPrint() 則依實際呼叫類別 (ChildClass 或 AnotherChildClass) 解析。

應用場景與最佳實務

情境建議用法
父類定義演算法骨架,子類實作細節父類用 $this->step() (Template Method Pattern)
靜態工廠方法回傳子類實例父類用 static::create() (LSB)
內部輔助方法,不希望被覆寫用 self::helper() 或 private 方法
Active Record 基類 find() 回傳子類集合用 static::hydrate() (LSB)

常見錯誤

  • 在 __construct() 中呼叫 $this->virtualMethod():子類尚未完全建構,可能存取未初始化屬性 → 改用 self:: 或延遲初始化。
  • 靜態方法中使用 $this:致命錯誤,靜態方法無 $this,必須用 self:: 或 static::。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved