Могут ли 2 одноэлементных класса ссылаться друг на друга? - PullRequest
3 голосов
/ 05 февраля 2011

Почему это не работает? Разве каждый экземпляр не должен просто ссылаться друг на друга один раз?

class foo {
    private static $instance;
    private function __construct() {
    $test = bar::get_instance();
    }

    public static function get_instance() {
        if (empty(self::$instance)) {
            self::$instance = new foo();
        }
        return self::$instance;
    }
}

class bar {
    private static $instance;
    public function __construct() {
    $test = foo::get_instance();
    }

    public static function get_instance() {
        if (empty(self::$instance)) {
            self::$instance = new bar();
        }
        return self::$instance;
    }
}

$test = foo::get_instance();

Ответы [ 4 ]

4 голосов
/ 05 февраля 2011

У вас есть то, что известно как циклическая зависимость .А для завершения требуется В, чтобы построить, а для завершения В требуется А, чтобы построить.Таким образом, это идет кругом навсегда.

По сути, происходит то, что self::$instance в каждом классе не заполняется до тех пор, пока не закончится new class().Итак, в конструкторе вы вызываете другой getInstance.Но каждый раз, когда вы нажимаете get_instance(), self::$instance все еще равен нулю, потому что предыдущий new никогда не заканчивался.И снова и снова вы идете.Это будет продолжаться до конца.

Вместо этого добавьте его после строительства:

class foo {
    private static $instance;
    private function __construct() {
    }
    private function setBar(bar $bar) {
        $this->bar = $bar;
    }

    public static function get_instance() {
        if (empty(self::$instance)) {
            self::$instance = new foo();
            self::$instance->setBar(bar::get_instance());
        }
        return self::$instance;
    }
}

class bar {
    private static $instance;
    public function __construct() {
    }
    private function setFoo(foo $foo) {
        $this->foo = $foo;
    }
    public static function get_instance() {
        if (empty(self::$instance)) {
            self::$instance = new bar();
            self::$instance->setFoo(foo::get_instance());
        }
        return self::$instance;
    }
}

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

3 голосов
/ 05 февраля 2011

У вас будет бесконечная рекурсия:

foo :: get_instance ();-> Конструктор foo -> bar :: get_instance () -> Конструктор bar -> foo :: get_instance ();-> ...

0 голосов
/ 05 февраля 2011

То, что у вас есть, это случай рекурсии.Стек вызовов выглядит следующим образом:

foo::get_instance() 
foo::__construct()
bar::get_instance()
bar::__construct()
foo::get_instance()
foo::__construct()
...

Причина, по которой это происходит, заключается в том, что когда foo :: get_Instance вызывается из конструктора bar, он все еще находится в контексте начального вызова foo::get_Instance иеще не установил значение $instance.

Существует несколько способов решения этой проблемы, но сначала я хотел бы спросить, почему вам нужно, чтобы они были членами друг друга.

Если вам это не нужно, вы просто позвоните foo::get_instance и bar::get_instance в те точки, к которым вам нужно получить доступ.

0 голосов
/ 05 февраля 2011

Потому что ни один конструктор никогда не вернется. Ни один экземпляр foo или bar никогда не создается, потому что они продолжают ссылаться друг на друга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...