class A {
protected static $_instance = null;
protected function __construct() {}
protected function __clone() {}
public function getInstance() {
if (self::$_instance === null) {
self::$_instance = new self();
}
return self::$_instance;
}
}
class B extends A {
protected static $_instance = null;
}
$a = A::getInstance();
$b = B::getInstance();
var_dump($a === $b); // bool(true) —— 子類共享了父類實例!
原因:self 在類定義時綁定,繼承類調用父類方法時 self::$_instance 仍指向父類屬性。
將 self 替換為 static,引用在運行時解析:
class C {
protected static $_instance = null;
protected function __construct() {}
protected function __clone() {}
public function getInstance() {
if (static::$_instance === null) {
static::$_instance = new static; // 關鍵:new static 而非 new self
}
return static::$_instance;
}
}
class D extends C {
protected static $_instance = null; // 必須重新聲明,隔離存儲
}
$c = C::getInstance();
$d = D::getInstance();
var_dump($c === $d); // bool(false) —— 完美隔離
protected 防止外部實例化/克隆。$_instance 在每個具體單例類中**必須重新聲明**,否則仍會共享。static::$_instance 和 new static 實現 LSB。getInstance。