使用 static 關鍵字宣告的屬性或方法稱為靜態成員。靜態方法無需實例化物件,直接透過 類別名::方法名() 呼叫;靜態屬性同樣透過 類別名::$屬性名 存取。
class A {
static function fun() {
// do something
}
}
A::fun(); // 直接呼叫
核心差異在於生命週期與 $this 的可用性:
$thisself:: 或 static::(晚期靜態綁定)$this 存取實例屬性class MyClass {
public $num = 5;
function __construct() {
$this->num = 10;
}
function fun_1() { // 非靜態方法
echo "I am a public method named fun_1.\n";
echo "The num of object is {$this->num}.\n";
}
static function fun_2() { // 靜態方法
echo "I am a static method named fun_2.\n";
}
function fun_3($n) {
echo "The arg is {$n}\n";
}
}
$m = new MyClass;
$m->fun_1(); // 正常
$m->fun_2(); // 正常(物件也可呼叫靜態方法)
$m->fun_3('test');
MyClass::fun_1(); // 錯誤:Using $this when not in object context
MyClass::fun_2(); // 正常
MyClass::fun_3('test'); // 錯誤
class User {
public static $username; // 靜態屬性
public $password; // 非靜態屬性
function __construct($pwd) {
echo 'Username: ' . self::$username;
self::$username = 'admin';
$this->password = $pwd;
}
public function show() {
echo 'Username: ' . self::$username;
echo 'Password: ' . $this->password;
}
public static function sshow() {
echo 'Username: ' . self::$username;
// echo 'Password: ' . $this->password; // 錯誤:靜態方法不可用 $this
}
}
User::$username = 'root'; // 實例化前即可存取
$objUser = new User('123456');
$objUser->sshow();
unset($objUser); // 物件銷毀
echo 'Username: ' . User::$username; // 靜態屬性依然存在
關鍵觀察:靜態屬性在類別實例化前就生效,物件銷毀後依然保留。這正是為什麼靜態方法無法存取非靜態成員——非靜態成員依賴具體實例存在。
| 成員類型 | 物件呼叫 | 類別名呼叫 | 可用 $this |
|---|---|---|---|
| 非靜態方法 | ✓ | ✗ (PHP 7+ 嚴格模式報錯) | ✓ |
| 靜態方法 | ✓ | ✓ | ✗ |
| 非靜態屬性 | ✓ | ✗ | ✓ |
| 靜態屬性 | ✗ | ✓ | ✗ |