2011-02-04 14 views
3

これはなぜ機能しないのですか?それぞれのインスタンスを単純に参照する必要はありませんか?2つのシングルトンクラスを互いに参照できますか?

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

あなたはcircular-dependencyとして知られているものを持っています。 Aは構築を完了するためにBを必要とし、Bは構築を完了するためにAを必要とする。だから永遠に丸くなります。

基本的には、各クラスのself::$instanceには、new class()が終了するまで入力されません。したがって、コンストラクタでは、もう一方をgetInstanceと呼んでいます。しかし、get_instance()を押すたびに、前のnewが決して壊れていないので、self::$instanceはまだヌルです。そしてラウンドラウンドで行く。それは終わりまで続けるでしょう。代わりに

、建設後にそれを追加します。

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; 
    } 
} 

あなたInject the Dependenciesいうよりは、自己依存シングルトンを作成するようにしかし、私は本当にを再設計するあなたの関係やクラスをお勧めします。

+0

ありがとう、私はそれを得る、意味をなさない。 – pmm

+1

@pmmmm:この回答があなたの問題を解決する場合、この回答のスコアの下にあるチェックボックスの輪郭にチェックを入れて[受け入れられるとマークする](http://stackoverflow.com/faq#howtoask)。それは、同じ問題があなたを助けてくれた人たちを見せてくれるのに役立ちます。 – ircmaxell

+0

これは競合状態ではありません。リンク先の記事を読んでください。 –

3

あなたは無限再帰があります:

FOO :: get_instanceを(); - > fooコンストラクタ - > bar :: get_instance() - > barコンストラクタ - > foo :: get_instance(); - > ...

+0

なぜですか?インスタンスが存在するので、両方のクラスのコンストラクタは一度だけ実行してはいけません。get_instance()は新しいインスタンスを起動しません。 – pmm

+0

いいえ、インスタンスをクラスに返すコンストラクタを呼び出します。無限再帰のためにコンストラクタが返ってくることはないので、 '$ instance'への代入は一切行われません。 – Patrik

0

どちらのコンストラクタも返さないためです。 fooまたはbarインスタンスは、互いに参照し続けるため、作成されていません。

0

ここには再帰のケースがあります。コールスタックは、次のようになります

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

これが起こっている理由は、FOO :: get_Instanceをバーコンストラクタから呼び出されたとき、それはfoo::get_Instanceに最初の呼び出しのコンテキストにまだあると設定していないということです$instance値はまだありません。

これに対処するにはいくつかの方法がありますが、どうしてなぜそれらを互いのメンバーにする必要があるのか​​を尋ねます。

必要がない場合は、アクセスする必要がある時点でfoo::get_instancebar::get_instanceと電話するだけです。

関連する問題