直截了当: 我有两个单身人士课程,都是从超级课程继承他们的单身人士。我在第一个单例上初始化了一些属性,然后让第二个单例检索第一个单例的 实例。然而,那个例子似乎并不是我最初初始化的那个例子。一些示例代码可能有助于解释这一点:
首先,超类,提供单身性质(需要PHP 5.3或更高版本):
class Singleton {
protected static $instance;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
if (!(static::$instance instanceof static)) {
static::$instance = new static();
}
return static::$instance;
}
}
然后我们得到了第一个带有值的单身人士:
require_once('Singleton.php');
class SingletonA extends Singleton {
protected $value;
public function SingletonA() {
$this->value = false;
}
public function getValue() {
return $this->value;
}
public function setValue($value) {
$this->value = $value;
}
}
然后引用第一个单例的第二个单例:
require_once('Singleton.php');
require_once('SingletonA.php');
class SingletonB extends Singleton {
public function getValue() {
return SingletonA::getInstance()->getValue();
}
}
现在进行测试,显示失败的原因:
require_once('SingletonA.php');
require_once('SingletonB.php');
SingletonA::getInstance()->setValue(true);
echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";
测试产生以下输出:
true
false
显然,测试代码引用的SingletonA实例与SingletonB实例引用的实例不同。简而言之,SingletonA并不像我需要的那样单一。这怎么可能?我能用什么魔法来弥补这种行为,给我一个真正的单身人士?
答案 0 :(得分:11)
尝试使用isset
而不是instanceof
:
class Singleton {
protected static $instances;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
答案 1 :(得分:0)
我很确定这是因为您使用的是非实例化的静态方法。
答案 2 :(得分:0)
SingletonA
和SingletonB
是不同的类。虽然它们是从同一个类继承的,但它们是独立的类,因此它们具有不同的静态实例。
如果您更改代码以获得SingletonA
的2个实例或SingletonB
的2个实例,您将看到您期望的行为。但因为它们是不同的类,它们不是同一个单身。
答案 3 :(得分:0)
我们来谈谈OO。 :)
SingletonA
和SingletonB
的类型为Singleton
SingletonA
Singleton
和
SingletonB
Singleton
即。 他们都是Singleton
Singleton
的预期含义意味着只能有一个。{使用您的代码的OO背景中的许多人将会感到困惑。
通常,Singleton的实现将基于每个类,因为大多数OO语言都不会倾向于允许您提出的意图。
PHP可能会做(通过get_called_class()
魔术)并不意味着应该这样做。
我绝对可以接受,从功利主义的角度来看,接受的答案看起来很好。考虑到已接受答案的优点,我建议更改一个与“标准”Singleton实现不冲突的名称。从严格的OO角度来看,人们永远不会从Singleton继承,所以它确实需要一个不同的名称。