PHP 5 類靜態成員詳解:靜態屬性、靜態方法、常量、self vs static 晚靜態綁定
本文為《Core PHP Programming》筆記第七節,深入講解 PHP 5 靜態成員機制:靜態屬性與方法的定義、訪問、內存模型、與實例成員的區別、self:: 與 static::(晚靜態綁定)的關鍵差異、常量用法,並通過 Counter 類對比演示普通方法與靜態方法的 $this 行為差異。
1. 靜態屬性:類級共享數據
class Counter {
private static $count = 0; // 僅一份拷貝,屬於類
public function __construct() { self::$count++; }
public function __destruct() { self::$count--; }
public static function getCount() { return self::$count; }
}
$c1 = new Counter();
$c2 = new Counter();
echo Counter::getCount(); // 2
- 聲明:
static $prop,可加訪問修飾符 public/private/protected static。
- 訪問:
ClassName::$prop 或 self::$prop/static::$prop(類內)。不可用 $this->prop。
- 生命周期:腳本啟動分配,腳本結束銷毀,跨請求不持久化(需配合 APCu/Redis)。
- 用途:計數器、配置緩存、單例實例持有、工廠註冊表等。
2. 靜態方法:類級行為,無 $this
class Counter {
private static $count = 0;
public static function getCount() {
// 此處無 $this 變量
return self::$count;
}
}
// 兩種調用方式均合法
echo Counter::getCount(); // 推薦:類名調用
$c = new Counter();
echo $c->getCount(); // 允許但不推薦:實例調用靜態方法,內部仍無 $this
- 聲明:
static function method()。
- 內部無 $this,不能訪問實例屬性/方法,只能訪問靜態成員。
- PHP 允許實例調用靜態方法(為兼容),但會發出
E_DEPRECATED(PHP 8.1+)。
- 判斷調用方式:
if (isset($this)) 區分實例/靜態調用(僅非 static 方法有效)。
3. 普通方法 vs 靜態方法對比
| 特性 | 普通方法 | 靜態方法 |
| 關鍵字 | function | static function |
| $this 可用性 | 是(指向當前實例) | 否(未定義) |
| 訪問實例成員 | 直接 $this->prop | 不可直接訪問 |
| 訪問靜態成員 | self::$staticProp | self::$staticProp |
| 調用方式 | $obj->method() | Class::method() 或 $obj->method()(不推薦) |
| 繼承行為 | 多態:子類覆寫生效 | 靜態綁定:self:: 綁定定義類 |
4. 晚靜態綁定:static:: vs self:: (PHP 5.3+)
class Base {
public static function who() { echo "Base\n"; }
public static function testSelf() { self::who(); } // 綁定 Base
public static function testStatic() { static::who(); } // 晚綁:調用類
}
class Derived extends Base {
public static function who() { echo "Derived\n"; }
}
Base::testSelf(); // Base
Base::testStatic(); // Base
Derived::testSelf(); // Base (self 綁定定義處)
Derived::testStatic(); // Derived (static 綁定調用處)
self:: 編譯時綁定到定義該方法的類。
static:: 運行時綁定到實際調用的類(Late Static Binding, LSB)。
- 工廠模式、ActiveRecord 基類、單例基類等場景必須用
static:: 才能正確支持繼承。
5. 類常量 const
class Config {
const VERSION = '1.0.0';
const MAX_RETRY = 3;
// const 總是 public static,不可加修飾符
}
echo Config::VERSION; // 1.0.0
// Config::VERSION = '2.0'; // 錯誤:常量不可修改
- 隱含
public static,不可用 private/protected。
- 用於不可變配置、狀態碼、版本號等。
- 子類可定義同名常量覆蓋(非繼承,屬於隱藏)。
6. 完整 Counter 示例(含版本常量)
class Counter {
private static $count = 0;
const VERSION = '2.0';
public function __construct() { self::$count++; }
public function __destruct() { self::$count--; }
public static function getCount() { return self::$count; }
}
$c = new Counter();
echo Counter::getCount(); // 1
echo Counter::VERSION; // 2.0
最佳實踐
- 靜態屬性默認
private,提供 public static getter/setter 控制訪問。
- 靜態方法內嚴禁使用
$this,靜態分析工具會報錯。
- 繼承體系中涉及靜態調用的工廠/單例/查找方法,統一使用
static::。
- 常量命名全大寫下劃線
MAX_RETRY,區別於屬性。
- 避免濫用靜態狀態導致全局耦合、難以測試;優先依賴注入傳遞服務實例。
- 上一篇文章: PHP 判斷 QQ 在線狀態:基於騰訊接口的 fsockopen 實現
- 下一篇文章: PHP 5 訪問控制詳解:public/private/protected、final、覆寫規則與封裝最佳實踐
Copyright ©
程式碼之家 All Rights Reserved