Was macht neues Selbst (); meine in PHP?

110

Ich habe noch nie einen solchen Code gesehen:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

Ist es das gleiche wie new className()?

BEARBEITEN

Wenn die Klasse vererbt ist, auf welche Klasse zeigt sie?

user198729
quelle
@ stereofrog, meinst du, Singleton-Muster sollten aufgegeben werden? Aber alle Dinge existieren aus einem Grund, oder?
user198729
Oh, ich stimme diesem Punkt eher zu: Singleton sollte durch Factory ersetzt werden
user198729
@stereofrog Singletons sind Gift für Unit-Tests. Es ist äußerst schwierig, unveränderliche Tests für etwas durchzuführen, das den Status von einem Anruf zum nächsten ändert.
David
Leider wird diese Methode nicht erweitert. Sie erhalten immer ein neues Objekt aus der Klasse, in der diese Funktion definiert wurde.
Ares

Antworten:

211

self zeigt auf die Klasse, in der es geschrieben ist.

Wenn sich Ihre getInstance-Methode in einem Klassennamen befindet MyClass, wird die folgende Zeile angezeigt :

self::$_instance = new self();

Wird das gleiche tun wie:

self::$_instance = new MyClass();



Bearbeiten: ein paar weitere Informationen nach den Kommentaren.

Wenn Sie zwei Klassen haben, die sich gegenseitig erweitern, haben Sie zwei Situationen:

  • getInstance wird in der untergeordneten Klasse definiert
  • getInstance wird in der übergeordneten Klasse definiert

Die erste Situation würde so aussehen (ich habe für dieses Beispiel den gesamten nicht erforderlichen Code entfernt - Sie müssen ihn wieder hinzufügen, um das Singleton-Verhalten zu erhalten) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Hier erhalten Sie:

object(MyChildClass)#1 (0) { } 

Was bedeutet selfbedeutetMyChildClass - dh die Klasse, in der es geschrieben ist.


Für die zweite Situation würde der Code folgendermaßen aussehen:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Und Sie würden diese Art von Ausgabe erhalten:

object(MyParentClass)#1 (0) { }

Was bedeutet selfbedeutet MyParentClass- dh auch hier die Klasse, in der es geschrieben ist .




Bei PHP <5.3 ist "die Klasse, in der es geschrieben ist" wichtig - und kann manchmal Probleme verursachen.

Aus diesem Grund führt PHP 5.3 eine neue Verwendung für das staticSchlüsselwort ein: Es kann jetzt genau dort verwendet werden, wo wir es verwendet habenself in diesen Beispielen verwendet haben:

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Aber mit staticstattself Sie jetzt:

object(MyChildClass)#1 (0) { } 

Was bedeutet, dass diese staticArt von Punkten auf die Klasse die verwendet wird (wir haben verwendetMyChildClass::getInstance() ), und nicht auf die, in der sie geschrieben ist.

Natürlich ist das Verhalten von self nicht geändert, um vorhandene Anwendungen nicht zu beschädigen - PHP 5.3 hat gerade ein neues Verhalten hinzugefügt, das das recyceltstatic Schlüsselwort recycelt.


Wenn Sie über PHP 5.3 sprechen, sollten Sie einen Blick auf die Seite Late Static Bindings des PHP-Handbuchs werfen .

Pascal MARTIN
quelle
@Paul: heu ... bedeutete "Selbst fungiert als Alias ​​für" oder "Selbst zeigt auf" - das Verb "Designer" auf Französisch kann dafür verwendet werden - ich nehme an, das ist eine der Situationen in dem es keine gute Idee ist, dasselbe Wort auf Englisch zu verwenden ;-( Ich werde meine Antwort bearbeiten, um dies zu beheben ;; danke :-)
Pascal MARTIN
Was ist baseclass, wenn es gibt , auf classwelches zeigt es?
user198729
@user: Ich habe meine Antwort bearbeitet, um ein bisschen mehr Informationen über selfund Vererbung zu geben. und ich habe auch einige Informationen über staticin PHP 5.3 aufgenommen ;; hoffe das hilft :-)
Pascal MARTIN
10

Dies scheint eine Implementierung des Singleton-Musters zu sein . Die Funktion wird statisch aufgerufen und prüft, ob die statische Klasse die Variable hat$_instance gesetzt ist.

Ist dies nicht der Fall, initialisiert es eine Instanz von sich selbst ( new self()) und speichert sie in$_instance .

Wenn Sie anrufen, erhalten className::getInstance()Sie ein und dasselbe bei jedem Aufruf Klasseninstanz. Dies ist der Punkt des Singleton-Musters.

Ich habe es jedoch noch nie so gesehen und wusste ehrlich gesagt nicht, dass es möglich ist. Was ist $_instancein der Klasse deklariert?

Pekka
quelle
1
$_instancewird erklärt alspublic static $_instance;
Atif
7

Dies wird höchstwahrscheinlich in Singleton-Entwurfsmustern verwendet, bei denen der Konstruktor als privat definiert ist, um eine Instanziierung zu vermeiden. Der Doppelpunktoperator (::)kann auf Elemente zugreifen, die innerhalb der Klasse als statisch deklariert sind. Wenn also statische Elemente vorhanden sind, die Pseudovariable $ Dies kann nicht verwendet werden, daher wird der Code selbst verwendet. Singletons sind gute Programmierpraktiken, die nur eine Instanz eines Objekts wie Datenbank-Connector-Handler zulassen. Der Zugriff auf diese Instanz erfolgt über den Clientcode, indem ein einzelner Zugriffspunkt erstellt wird. In diesem Fall hat er ihn benanntgetInstance() . Die getInstance an sich war die Funktion, mit der das Objekt im Wesentlichen mit dem neuen Schlüsselwort erstellt wurde, um ein Objekt zu erstellen, dh die Konstruktormethode auch genannt.

Die Zeile if(!isset(self::instance))prüft, ob bereits ein Objekt erstellt wurde. Sie konnten dies nicht verstehen, da der Code nur ein Fragment ist. Irgendwo oben sollten statische Elemente vorhanden sein, wie wahrscheinlich

private static $_instance = NULL; 

In normalen Klassen hätten wir einfach auf dieses Mitglied zugegriffen

$this->_instance = 'something';

aber es ist statisch deklariert und so konnten wir den $ this-Code nicht verwenden, den wir stattdessen verwenden

self::$_instance

Durch Überprüfen, ob in dieser statischen Klassenvariablen ein Objekt gespeichert ist, kann die Klasse entscheiden, ob eine einzelne Instanz erstellt werden soll oder nicht. Wenn sie also nicht gesetzt ist, gibt es kein Objekt auf dem statischen Element $ _instance an Es generiert ein neues Objekt und speichert es $_instancemit dem Befehl im statischen Element

self::$_instance = new self();

und gab es an den Client-Code zurück. Der Client-Code kann dann problemlos die einzelne Instanz des Objekts mit seinen öffentlichen Methoden verwenden, aber im Client-Code, der den einzelnen Zugriffspunkt aufruft, dh die getInstance()Methode ist auch schwierig, muss sie so aufgerufen werden

$thisObject = className::getInstance();

Aus diesem Grund wird die Funktion an sich als statisch deklariert.

flimh
quelle
2

Ja, es ist wie new className()(bezogen auf die Klasse, die diese Methode enthält), wahrscheinlich in einem Singleton-Muster verwendet, in dem der Konstruktor privat ist.

Matteo Riva
quelle
Warum sollte jemand das Singleton-Muster in PHP verwenden? Sofern nicht in einem daemonähnlichen Programm verwendet, lebt der Singleton nur, während das Skript ausgeführt wird, und verschwindet dann zusammen mit dem Programm.
ILikeTacos
4
um zu vermeiden, irritierend global zu deklarieren, um auf eine globale Variable zuzugreifen
Sam Adamsh
0

Wenn die Klasse geerbt wird, erhalten Sie durch Aufrufen von getInstance () von child keine Instanz von child. Es wird nur eine Instanz der übergeordneten Instanz zurückgegeben. Dies liegt daran, dass wir neues Selbst () nennen.

Wenn Sie möchten, dass die untergeordnete Klasse eine Instanz der untergeordneten Klasse zurückgibt, verwenden Sie new static () in getInstance () und geben Sie dann die untergeordnete Klasseninstanz zurück. Dies nennt man späte Bindung !!

kta
quelle