【问题标题】:PHP singletons and inheritancePHP单例和继承
【发布时间】:2013-06-10 20:43:24
【问题描述】:

我在使用 PHP 继承时遇到了一些问题。这是交易:

我有这个基类,Singleton:

namespace My_Namespace;

abstract class Singleton {
    protected static $instance = null;

    static function get() {
        if ( null == static::$instance ) {
            static::$instance = new static;
        }
        return static::$instance;
    }

    private function __construct() {

    }
}

我有一堆继承了 Singleton 类的类,称它们为 A、B、C、D。其中一个看起来像这样:

namespace My_Namespace;

class A extends Singleton {

    protected function __construct() {

        B::get();

        if ( some_condition() ) {
            C::get();
        }
        else {
            D::get();
        }
    }
}

现在,我只需执行 A::get() 即可让一切顺利进行。正如预期的那样,调用了 A 的构造函数。然后,调用 B 的构造函数,同样没有问题。现在变得很奇怪。一旦调用了C::get(),它就会将static::$instance 识别为B 类的对象并且根本不实例化C。我知道我是否有点菊花链式连接它们,即 B 调用 C::getD::get__construct 它可以工作,但这对我的目的来说不是最佳的。这是因为它们在同一范围内吗?如果是这样,有没有办法解决这个问题?我问这个更多的是出于好奇而不是实际目的——我知道我可以很容易地在它们中的每一个中实现单例模式。那么,有什么想法吗?谢谢!

附:请不要“单身人士是邪恶的,你应该在地狱中燃烧”cmets。我很清楚这一点。

【问题讨论】:

  • no ... burn in hell comments+1
  • 我相信继承的类需要一个静态属性才能将实例推入......所以将protected static $instance = null;添加到子类中。
  • @Orangepill 你明白了。我添加了那条线,一切都按预期工作。 BUT: 这有点让整个 Singleton 类和继承的东西毫无用处......我们的想法是将单例功能包含在该类中。这可能吗?
  • 不...如果您没有将其塞入其中的属性,它将回退到继承属性,从静态意义上讲,它是基类类属性。 :(

标签: php class inheritance static singleton


【解决方案1】:

请注意,static::$instance = new static 调用(在您的情况下)A 的构造函数。

使用您的解决方案,您的子类中的实例将需要一个静态属性。

只需添加

protected static $instance = null;

对他们来说,它应该可以正常工作。

【讨论】:

  • 为什么它在前两次有效?如果我不在同一个范围内,就像A::get()B::get() 一样,它会创建适当的实例,但是一旦它到达C::get(),它就会退回到它用于B::get 的实例?这有意义吗?
  • 前两次不行,第一次可以。你打电话给A::get()。然后调用A的构造函数。调用B::get(),而不是设置基类中的$instance(第一次设置)。现在你想调用C::get(),它检查null == static::$instance,但现在$instance (来自A类)已经是一个对象了。
  • 我花了一段时间才意识到解释是多么简单。在static::$instance = new static 处,构造函数被调用,该构造函数调用另一个构造函数,所有这些都是在将任何内容分配给实际的 $instance 变量之前,因为它还没有返回。傻我。感谢您的回答。
  • 没问题,顺便说一句:也许你也应该把final private function __clone() { } 放到你的单例中,以防止对象克隆
【解决方案2】:

在处理静态属性时,如果您希望继承类的静态属性与基类不同,您必须为其提供一个安身之所。

要解决问题只需定义

protected static $instance = null;

在您的派生类上。如果不是,它将使用基类的属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多