2013-06-10 17 views
5

Ich habe einige Probleme mit PHP-Vererbung. Hier Deal:PHP Singletons und Vererbung

Ich habe diese Basisklasse, 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() { 

    } 
} 

Ich habe eine Reihe von Klassen erben, dass Singleton-Klasse, nennen sie A, B, C, D. Einer von ihnen sieht wie folgt aus:

namespace My_Namespace; 

class A extends Singleton { 

    protected function __construct() { 

     B::get(); 

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

Nun, ich habe nur ein A::get() alles ins Rollen. Der Konstruktor von A wird wie erwartet aufgerufen. Dann wird der Konstruktor von B aufgerufen, wiederum ohne ein Problem. Jetzt wird es komisch. Sobald C::get() aufgerufen wird, erkennt es static::$instance als bereits ein Objekt der Klasse B und instanziiert C überhaupt nicht. Ich weiß, wenn ich sie irgendwie verkette, das ist __construct B Anrufe C::get oder D::get es funktioniert, aber das ist nicht optimal für meine Zwecke. Liegt das daran, dass sie im selben Umfang sind? Wenn ja, gibt es einen Weg dahin? Ich frage das eher nach Neugier als nach praktischem Zweck - ich weiß, dass ich das Singleton-Muster in jedem von ihnen genauso einfach implementieren kann. Also, irgendwelche Ideen? Vielen Dank!

P.S. Bitte keine "Singletons sind böse und du solltest in der Hölle brennen" Kommentare. Das weiß ich ganz genau.

+1

+1 für 'no ... brennen in der Hölle comments' – phpisuber01

+1

Ich glaube, die geerbten Klassen benötigen eine statische Eigenschaft für die Instanz in ... verschachtelt werden ... also fügen Sie' protected static $ instance = null; 'zu den Unterklassen . – Orangepill

+0

@Orangepill du hast es. Ich habe diese Zeile hinzugefügt und alles funktioniert wie erwartet. 'ABER:' Das macht die gesamte Singleton-Klasse und die Vererbungstools nutzlos, obwohl ... Die Idee war, die Singleton-Funktionalität in dieser Klasse enthalten zu haben. Ist das überhaupt möglich? –

Antwort

2

Beachten Sie, dass static::$instance = new static den Konstruktor von (in Ihrem Fall) A aufruft.

Mit Ihrer Lösung benötigen Sie eine statische Eigenschaft für Ihre Instanz in Ihren Unterklassen.

Fügen Sie einfach

protected static $instance = null; 

zu ihnen, und es sollte funktionieren.

+0

Warum funktioniert es für die ersten beiden Male? Wie kommt es, wenn ich nicht im gleichen Umfang bin, wie in 'A :: get()' und 'B :: get()' es erstellt die entsprechenden Instanzen aber sobald es 'C :: get()' trifft, fällt es zurück zu dem, das es für 'B :: get' verwendet hat? Ist das sinnvoll? –

+1

Es funktioniert nicht für die ersten beiden Male, es funktioniert Zum ersten Mal rufen Sie 'A :: get()'. Dann wird der Konstruktor von 'A' aufgerufen, der' B :: get() 'aufruft, als die' $ instance' aus der ** Basisklasse * * ist gesetzt (das erste Mal, dass es gesetzt ist). Und jetzt wollen Sie 'C :: get()' aufrufen, das überprüft 'null == static :: $ instance', aber jetzt die' $ instance' ** (aus Klasse A) ** ist bereits ein Objekt. – bpoiss

+0

Nahm mich eine Weile, um zu erkennen, wie einfach die Erklärung ist. Bei dieser 'static :: $ instance = new static' wird der Konstruktor aufgerufen, der einen anderen Konstruktor aufruft, bevor er der tatsächlichen $ instance-Variablen etwas zuordnet, weil er noch nicht zurückgegeben wurde. Wie dumm von mir. Danke für die Antwort. –

1

Wenn mit statischen Eigenschaften zu tun, wenn Sie die geerbte Klassen der statischen Eigenschaften von den Basisklassen unterscheiden mögen Sie ein Haus schaffen, müssen es in leben.

Um das Problem zu lösen, nur

definieren
protected static $instance = null; 

für Ihre abgeleitete Klasse. Wenn nicht, wird die Eigenschaft der Basisklasse verwendet.