static 是 PHP 面向對象編程中極具特色的關鍵字,它改變了成員屬於「實例」還是「類」的歸屬關係,也賦予了函數內變量「跨調用保持狀態」的能力。本文從語法、記憶體模型、繼承規則、常見誤區四個維度徹底講透。
<?php
class Person {
public static $country = "中國"; // 靜態屬性
public $name = "張三"; // 實例屬性
}
echo Person::$country; // 輸出:中國(無需實例化)
$p1 = new Person();
// echo $p1->country; // 錯誤:靜態屬性不能通過對象訪問
$p1->name = "李四"; // 正常:實例屬性屬於對象
記憶體模型:靜態屬性在類加載時分配一次內存,所有實例共享同一塊地址;實例屬性隨 new 分配,各自獨立。
class Person {
public static $country = "中國";
public static function myCountry() {
echo "我是 " . self::$country . " 人<br>"; // 內部用 self::
}
public function sayHello() {
echo "Hello, I'm " . $this->name . "<br>"; // 非靜態可用 $this
}
}
Person::myCountry(); // 類名調用
$p = new Person();
$p->myCountry(); // 對象調用靜態方法:合法但不推薦(易誤導)
// $p->sayHello(); // 需實例化
核心限制:靜態方法內 不可使用 $this,不可訪問非靜態屬性/方法。但可訪問靜態屬性/方法(用 self:: 或 static::)。
function counter() {
static $count = 0; // 僅初始化一次
$count++;
echo $count . "<br>";
}
counter(); // 1
counter(); // 2
counter(); // 3
static $x = strlen("abc"); ❌)。function recurse($n) {
static $depth = 0;
$depth++;
echo "Depth: $depth<br>";
if ($depth < $n) recurse($n);
$depth--; // 回溯恢復
}
recurse(3);
class ParentClass {
public static $who = "Parent";
public static function test() {
echo "self::\$who = " . self::$who . "<br>"; // 編譯期綁定 → Parent
echo "static::\$who = " . static::$who . "<br>"; // 運行期綁定 → 實際調用類
}
}
class ChildClass extends ParentClass {
public static $who = "Child";
}
ChildClass::test();
輸出:
self::$who = Parent
static::$who = Child
| 關鍵字 | 綁定時機 | 訪問靜態屬性 | 訪問靜態方法 |
|---|---|---|---|
self:: | 編譯期(定義所在類) | ✅ | ✅ |
static:: | 運行期(實際調用類,晚期靜態綁定 LSB) | ✅ | ✅ |
parent:: | 編譯期(父類) | ✅ | ✅ |
類名:: | 編譯期(指定類) | ✅ | ✅ |
$obj-> | 運行期(對象實例) | ❌ 靜態屬性 | ✅ 僅靜態方法 |
$obj->staticProp 可讀寫靜態屬性。E_DEPRECATED(8.1+),語義混淆。統一用 Class::$prop。self:: 調用其他靜態方法,改為非靜態後 self:: 仍指向原類,導致 LSB 失效。重構時需同步改為 static::。static $var。static::(LSB)。class Singleton {
private static $instance = null;
private function __construct() {}
private function __clone() {}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function doSomething() { echo "Working...<br>"; }
}
Singleton::getInstance()->doSomething();
static 三大用法——靜態屬性/方法(類級共享)、靜態變量(函數級持久)、晚期靜態綁定 static::(繼承多態)——各有其記憶體語義與適用場景。搞清 self::(編譯期)與 static::(運行期)的區別,是進階 PHP OOP 的分水嶺。