我有一个带有单例函数 instance() 和关联变量 $instance 的主类。现在我创建几个子类并让主类继承。我没有重新定义单例函数和变量,因为继承很有用。不幸的是,每个实例都指向第一个子类。只有在子类中 $instance 变量被初始化为 null 时它才起作用,但为什么呢?使用关键字 static 而不是 self 时,作用域应保留在子类中。
这里是源代码,可以更好地理解我的意思:
// PHP Version 7.0
// Don't work as expected:
class base1
{
/*
* Instance of class
* mixed
*/
protected static $instance = null;
/*
* For Singleton Pattern
*/
public static function instance() {
if ( null == static::$instance ) {
static::$instance = new static();
}
return static::$instance;
}
public function test()
{
$test = "base1";
var_dump($test);
}
}
class sub11 extends base1
{
public function test()
{
$test = "base1 -> sub11";
var_dump($test);
}
}
class sub12 extends base1
{
public function test()
{
$test = "base1 -> sub12";
var_dump($test);
}
}
$sub11 = sub11::instance();
$sub12 = sub12::instance();
$sub11->test();
$sub12->test();
// Output:
// string(14) "base1 -> sub11"
// string(14) "base1 -> sub11" // It's not different!!!
// Work as expected:
class sub21 extends base1
{
/*
* Instance of class
* mixed
*/
protected static $instance = null; // Is needed, but why?
public function test()
{
$test = "base1 -> sub21";
var_dump($test);
}
}
class sub22 extends base1
{
/*
* Instance of class
* mixed
*/
protected static $instance = null; // Is needed, but why?
public function test()
{
$test = "base1 -> sub22";
var_dump($test);
}
}
$sub21 = sub21::instance();
$sub22 = sub22::instance();
$sub21->test();
$sub22->test();
// Output:
// string(14) "base1 -> sub21"
// string(14) "base1 -> sub22" // This is correct !
最佳答案
在您的第一部分中,它工作正确并且符合预期。 sub11 和 sub12 类都使用 base1 的字段来存储实例。因此,第一个已启动的实例被放置在那里并防止其他人覆盖已经创建的实例。
在第二部分中,您为每个后代类指定了个人静态存储字段,因此它们不使用基类字段,而是使用自己的字段(它与父字段重叠,因为使用相同的名称)。
简而言之,第一对后代类使用base1::$instance
来检查和创建实例。第二对使用自己的字段 sub21::$instance
和 sub22::$instance
来完成此任务。
您可以通过丢弃 base1 类中的后期静态绑定(bind)来防止这种情况:
class base1
{
/*
* Instance of class
* mixed
*/
protected static $instance = null;
/*
* For Singleton Pattern
*/
public static function instance() {
if ( null == self::$instance ) {
// ^ self instead of static
self::$instance = new static();
// ^ self instead of static
}
return self::$instance;
// ^ self instead of static
}
public function test()
{
$test = "base1";
var_dump($test);
}
}
我真的建议您阅读 late static binding以及 self
和 static
关键字之间的区别。
UPDv1:
如果您仍然需要仅获取每个后代类的一个实例,您可以将 singleton 方法更改为如下所示:
class base1
{
/*
* Instances of descendant classes
* array
*/
protected static $instances = [];
/*
* For Singleton Pattern
*/
public static function instance() {
if (empty(self::$instances[static::class])) {
$instance = new static();
self::$instances[static::class] = $instance;
} else {
$instance = self::$instances[static::class];
}
return $instance;
}
public function test()
{
$test = "base1";
var_dump($test);
}
}
关于php - 仅当重新初始化继承类中的实例变量时,PHP 中使用单例模式的类继承才有效。但为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45500377/