2013-06-10 31 views
5

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()が呼び出されると、既にクラスBのオブジェクトとしてstatic::$instanceが認識され、Cをインスタンス化しません。 Bの__constructC::getまたはD::getを呼び出しているが、それが私の目的には最適ではないことがわかっている。それはそれらが同じ範囲にあることによって引き起こされるのでしょうか?もしそうなら、これを回避する方法はありますか?実用目的ではなく好奇心をもっと求めています。私は、それぞれのシングルトンパターンを簡単に実装できることを知っています。だから、どんなアイデアですか?ありがとう!

P.S. 「シングルトンは悪ではなく、あなたは地獄で燃えるべきです」というコメントはしないでください。私はそれを完全によく知っています。

+1

+1のために地獄のコメントで焼く – phpisuber01

+1

私は、継承されたクラスにインスタンスを押し込む静的なプロパティが必要だと思うので、 'protected static $ instance = null;'をサブクラスに追加してください。 – Orangepill

+0

@Orangepillあなたはそれを持っています。私はその行を追加し、それはすべて期待どおりに動作します。 'しかし、それはシングルトンのクラス全体と継承のものを役に立たなくしてしまいます...そのアイデアは、そのクラスにシングルトンの機能を入れさせることでした。それはまったく可能ですか? –

答えて

2

static::$instance = new staticは、(あなたの場合は)Aのコンストラクタを呼び出します。

解決策では、サブクラスでインスタンス用の静的プロパティが必要になります。

ちょうどそれらに

protected static $instance = null; 

を追加し、それが正常に動作する必要があります。

+0

なぜ最初の2回はうまくいくのですか? 'A :: get()'と 'B :: get()'と同じスコープにないと、しかし、 'C :: get()'にヒットすると、 'B :: get'のために使用されたものに戻ってしまいますか?それは意味がありますか? –

+1

最初の2回は動作しません。最初に 'A :: get()'を呼び出すと、 'A'のコンストラクタが呼び出され、**基本クラスの' $ instance'より 'B :: get()'が呼び出されます。 *これは 'null ::= static :: $ instance'をチェックする' C :: get() 'を呼び出したいが、今は' $ instance' **(クラスAから)**はすでにオブジェクトです。 – bpoiss

+0

説明がどれくらい簡単か分かりました。その 'static :: $ instance = new static'では、実際に$ instance変数に何かを代入する前に別のコンストラクタを呼び出すコンストラクタが呼び出され、それはまだ返されません。愚かな私。答えをありがとう。 –

1

あなたが継承したクラスの静的プロパティは、あなたがそれをして生活するために家を提供する必要が基底クラスと異なるしたい場合は、静的プロパティを扱う。

だけの定義の問題を解決するために

protected static $instance = null; 
派生クラスの

それ以外の場合は、基本クラスのプロパティを使用します。