Que signifie new self (); signifie en PHP?

110

Je n'ai jamais vu de code comme celui-ci:

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

Est-ce la même chose que new className()?

ÉDITER

Si la classe est héréditaire, vers quelle classe elle pointe?

user198729
la source
@ stéréofrog, voulez-vous dire que le modèle singleton devrait être abandonné? Mais tout existe pour une raison, non?
user198729
Oh, j'ai tendance à être d'accord avec ce point: singleton devrait être remplacé par factory
user198729
Les @stereofrog Singleton sont un poison pour les tests unitaires, il est extrêmement difficile de faire des tests immuables sur quelque chose qui change d'état d'un appel à l'autre.
David
Malheureusement, cette méthode ne s'étendra pas. Il vous donnera toujours un nouvel objet de la classe dans laquelle cette fonction a été définie.
Ares

Réponses:

211

self pointe vers la classe dans laquelle il est écrit.

Donc, si votre méthode getInstance est dans un nom de classe MyClass, la ligne suivante:

self::$_instance = new self();

Fera la même chose que:

self::$_instance = new MyClass();



Edit: quelques informations supplémentaires, après les commentaires.

Si vous avez deux classes qui s'étendent l'une l'autre, vous avez deux situations:

  • getInstance est défini dans la classe enfant
  • getInstance est défini dans la classe parente

La première situation ressemblerait à ceci (j'ai supprimé tout le code non nécessaire, pour cet exemple - vous devrez le rajouter pour obtenir le comportement singleton) *:

class MyParentClass {

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

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

Ici, vous obtiendrez:

object(MyChildClass)#1 (0) { } 

Ce qui veut selfdireMyChildClass - c'est-à-dire la classe dans laquelle il est écrit.


Pour la deuxième situation, le code ressemblerait à ceci:

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

}

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

Et vous obtiendrez ce genre de sortie:

object(MyParentClass)#1 (0) { }

Ce qui signifie selfsignifie MyParentClass- c'est-à-dire ici aussi, la classe dans laquelle il est écrit .




Avec PHP <5.3, que «la classe dans laquelle elle est écrite» est importante - et peut parfois causer des problèmes.

C'est pourquoi PHP 5.3 introduit une nouvelle utilisation du staticmot - clé: il peut maintenant être utilisé exactement là où nous l'avons utilisé selfdans ces exemples:

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

}

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

Mais, avec staticau lieu de self, vous obtiendrez maintenant:

object(MyChildClass)#1 (0) { } 

Ce qui signifie que cette staticsorte de pointage vers la classe utilisée (nous avons utiliséMyChildClass::getInstance() ), et non celle dans laquelle elle est écrite.

Bien sûr, le comportement de selfn'a pas été changé, pour ne pas casser les applications existantes - PHP 5.3 vient d'ajouter un nouveau comportement, recyclant lestatic mot clé.


Et, en parlant de PHP 5.3, vous voudrez peut-être jeter un œil à la page Late Static Bindings du manuel PHP.

Pascal MARTIN
la source
@Paul: heu ... signifiait "self agit comme un alias de", ou "self sorte de points to" - le verbe "designer", en français, peut être utilisé pour cela - je suppose que c'est l'une des situations dans lequel utiliser le même mot en anglais n'est pas une bonne idée ;-( Je vais éditer ma réponse pour résoudre ce problème ;; merci :-)
Pascal MARTIN
Et s'il y a baseclass, classqui on le fait pointer?
user198729
@user: J'ai édité ma réponse pour donner un peu plus d'informations sur selfet l'héritage; et j'ai également inclus des informations sur staticPHP 5.3 ;; j'espère que cela aide :-)
Pascal MARTIN
10

Cela semble être une implémentation du modèle Singleton . La fonction est appelée statiquement et vérifie si la classe statique a la variable$_instance jeu de .

Si ce n'est pas le cas, il initialise une instance de lui-même ( new self()) et la stocke dans$_instance .

Si vous appelez, className::getInstance()vous obtiendrez un seul et même instance de classe à chaque appel, qui est le point du motif singleton.

Cependant, je n'ai jamais vu cela ainsi, et honnêtement, je ne savais pas que c'était possible. Qu'est-ce qui est $_instancedéclaré comme dans la classe?

Pekka
la source
1
$_instanceest déclaré commepublic static $_instance;
Atif
7

Ceci est très probablement utilisé dans le modèle de conception singleton, dans lequel le constructeur est défini comme privé afin d'éviter d'être instancié, l' (::)opérateur double-virgule peut accéder aux membres déclarés statiques à l'intérieur de la classe, donc s'il y a des membres statiques, la pseudo variable $ cela ne peut pas être utilisé, d'où le code utilisé à la place, les singletons sont de bonnes pratiques de programmation qui n'autoriseront qu'une seule instance d'un objet comme les gestionnaires de connecteurs de base de données. À partir du code client, l'accès à cette instance se ferait en créant un point d'accès unique, dans ce cas, il l'a nommégetInstance() , le getInstance en lui-même était la fonction qui a créé l'objet en utilisant essentiellement le mot-clé new pour créer un objet, ce qui signifie que la méthode du constructeur était aussi appelé.

la ligne if(!isset(self::instance))vérifie si un objet a déjà été créé, vous ne pouviez pas comprendre cela car le code n'est qu'un fragment, quelque part en haut, il devrait y avoir des membres statiques comme probablement

private static $_instance = NULL; 

dans les classes normales, nous aurions accédé à ce membre simplement

$this->_instance = 'something';

mais il est déclaré statique et nous ne pouvons donc pas utiliser le code $ this que nous utilisons à la place

self::$_instance

en vérifiant s'il y a un objet stocké sur cette variable de classe statique, la classe peut alors décider de créer ou non une seule instance, donc si elle n'est pas définie,! isset, ce qui signifie qu'aucun objet n'existe sur le membre statique $ _instance, alors il génère un nouvel objet, stocké dans le membre statique $_instancepar la commande

self::$_instance = new self();

et l'a renvoyé au code client. Le code client peut alors utiliser avec plaisir l'instance unique de l'objet avec ses méthodes publiques, mais dans le code client, appeler le point d'accès unique, c'est-à-dire que la getInstance()méthode est également délicate, elle doit être appelée comme ceci

$thisObject = className::getInstance();

la raison, la fonction en elle-même est déclarée statique.

flimh
la source
2

Oui, c'est comme new className()(en référence à la classe contenant cette méthode), probablement utilisé dans un modèle Singleton où le constructeur est privé.

Matteo Riva
la source
Pourquoi quelqu'un utiliserait-il le modèle Singleton en PHP? À moins d'être utilisé dans un programme de type démon, le singleton ne vivra que pendant l'exécution du script, puis disparaîtra avec le programme.
ILikeTacos
4
pour éviter de déclarer globalement irritant pour accéder à une variable globale
Sam Adamsh
0

Si la classe est héritée, appeler getInstance () depuis child ne vous donnera pas d'instance de child. Il ne retournera qu'une instance de l'instance parent. C'est parce que nous appelons le nouveau self ().

Si vous voulez que la classe enfant renvoie une instance de classe enfant, utilisez new static () dans getInstance () et elle retournera ensuite l'instance de classe enfant. C'est ce qu'on appelle la liaison tardive !!

kta
la source