兩種訪問方式對比
| 方式 | 語法 | 需實例化 | 構造函數 | 適用成員 |
| 實例訪問 | $obj = new Class(); $obj->prop | 是 | 執行 | 非靜態/靜態均可 |
| 類名訪問 | Class::$prop | 否 | 不執行 | 靜態/非靜態(有條件) |
靜態屬性特性
- 共享單一存儲:類的所有實例共享同一靜態屬性值
- 生命週期:隨腳本啟動分配,腳本結束釋放
- 繼承行為:子類未覆寫時共享父類靜態屬性;覆寫後獨立存儲
class ParentClass {
public static $count = 0;
}
class ChildClass extends ParentClass {}
ParentClass::$count = 1;
echo ChildClass::$count; // 1(共享)
ChildClass::$count = 2;
echo ParentClass::$count; // 2(仍共享,未覆寫)
// 覆寫後獨立
class Child2 extends ParentClass {
public static $count = 10;
}
ParentClass::$count = 5;
echo Child2::$count; // 10(獨立)
靜態方法訪問規則
類名訪問靜態方法:無限制
class Demo {
public static function staticFunc() { echo 'static'; }
public function instanceFunc() { echo 'instance'; }
}
Demo::staticFunc(); // 正常
類名訪問非靜態方法:嚴格條件
- 方法**不使用
$this**
- 方法**不調用非靜態屬性/方法**
- 僅調用靜態成員或無狀態邏輯
class Demo {
public static $s = 'static';
public $i = 'instance';
public function test() {
echo self::$s; // 允許
// echo $this->i; // 致命錯誤:非靜態上下文使用 $this
}
}
Demo::test(); // 正常輸出 static
實例化與靜態調用的關鍵差異
| 場景 | new Class() | Class::method() |
| 構造函數 | 執行 | 不執行 |
| 記憶體分配 | 分配對象結構 | 無對象分配 |
| $this 可用性 | 可用 | 不可用(除非在實例方法中) |
| 適用場景 | 需要對象狀態 | 工具方法、工廠、單例入口 |
最佳實踐指南
- 無狀態工具類:全靜態,如
StringUtils::trim()、ArrayHelper::merge()
- 單例模式:私有構造 + 靜態
getInstance() 返回實例
- 工廠方法:靜態
create() 封裝實例化邏輯
- 避免濫用靜態:難測試、難 Mock、隱式依賴、全局狀態污染
- 晚期靜態綁定 (LSB):使用
static:: 而非 self:: 實現多態
晚期靜態綁定範例
class Model {
public static function tableName() {
return 'model';
}
public static function find() {
echo 'Querying ' . static::tableName(); // LSB
}
}
class User extends Model {
public static function tableName() {
return 'user';
}
}
User::find(); // 輸出:Querying user
內存模型圖解
類定義區(方法區)
├── 靜態屬性表 → 單一值存儲
├── 方法表 → 靜態/非靜態方法代碼
└── 常量表
運行時堆
├── 對象實例 1 → 實例屬性表(含指向類定義的指針)
├── 對象實例 2 → 實例屬性表
└── ...
靜態屬性屬於**類**,不屬於任何實例,存儲於方法區(PHP 內部實現為類結構體成員)。