<?php
class Trones {
public static $fire = 'I am fire.';
public $water = 'I am water';
public static function getFire() {
return $this->fire; // ❌ Fatal Error
}
public static function getWater() {
return self::$water; // ❌ Fatal Error: 非靜態屬性不可用 self::
}
public static function getFireCorrect() {
return self::$fire; // ✅ 靜態方法只能存取靜態屬性
}
}
Trones::getFireCorrect(); // 正常
$obj = new Trones();
$obj->fire; // Notice: 靜態屬性不可用 -> 操作
> **鐵律**:**靜態方法中不可使用 `$this`**,只能用 `self::` 或 `static::` (晚期靜態綁定) 存取**靜態成員**。
| 關鍵字 | 類別內部 | 繼承類別 | 外部 |
|---|---|---|---|
| `public` | ✅ | ✅ | ✅ |
| `protected` | ✅ | ✅ | ❌ |
| `private` | ✅ | ❌ | ❌ |
class Trones {
protected $fire = 'fire';
public $water = 'water';
private static $trones = 'Trones';
protected function getFire() { return $this->fire; }
public static function theDragon() {
return __METHOD__ . ' uses ' . $this->getFire() . ' gets ' . self::getTrones(); // ❌ $this 在 static
}
public static function getWater() { return __METHOD__; }
private static function getTrones() { return self::$trones; }
}
class Kings extends Trones {
public static function sevenKing() {
return self::getTrones(); // ❌ private 父類別方法不可繼承
}
}
class People extends Trones {
public static function thePeople() {
return self::getTrones(); // ❌ 同上
}
}
> **解決**:
> 1. 靜態方法移除 `$this->getFire()` 呼叫。
> 2. 父類別 `private static` 改為 `protected static` 讓子類別可用 `parent::` 或 `static::`。
> 3. 子類別覆寫靜態方法時,`self::` 指向**當前類別**,`static::` 指向**實際調用類別** (晚期靜態綁定)。
class A {
public static function who() { echo __CLASS__; }
public static function test() { self::who(); } // 輸出 A
public static function testLSB() { static::who(); } // 輸出實際調用類別
}
class B extends A {
public static function who() { echo __CLASS__; }
}
B::test(); // A (self:: 綁定寫死)
B::testLSB(); // B (static:: 動態解析)
原文摘自 warcraft