Синглеты PHP и наследование


У меня возникли некоторые проблемы с наследованием PHP. Вот в чем дело:

У меня есть этот базовый класс, Синглтон:

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() {

    }
}

У меня есть куча классов, наследующих этот одноэлементный класс, назовите их 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. Я знаю, что если я как бы соединяю их в цепочку, то есть __construct вызовов B C::get или D::get, это работает, но это не оптимально для моих целей. Это вызвано тем, что они находятся в одном и том же объеме? Если да, то есть ли какой-нибудь способ обойти это? Я спрашиваю об этом скорее из любопытства, чем с практической целью - я знаю, что могу так же легко реализовать шаблон одноэлементного в каждом из них. Итак, есть какие-нибудь идеи? Спасибо!

P.S. Пожалуйста, не "синглеты - это зло, и вы должны гореть в аду" комментарии. Я это прекрасно знаю.

Author: Dobromir Yordanov, 2013-06-11

2 answers

Обратите внимание, что static::$instance = new static вызывает конструктор (в вашем случае) A.

С вашим решением вам понадобится статическое свойство для вашего экземпляра в ваших подклассах.

Просто добавьте

protected static $instance = null;

Для них, и это должно работать нормально.

 2
Author: bpoiss, 2013-06-11 19:22:47

При работе со статическими свойствами, если вы хотите, чтобы статические свойства унаследованных классов отличались от базовых классов, вы должны предоставить им дом для проживания.

Чтобы решить проблему, просто определите

protected static $instance = null;

В вашем производном классе. Если нет, он будет использовать свойство базового класса.

 1
Author: Orangepill, 2013-06-10 20:53:56