web-dev-qa-db-fra.com

Que fait le nouveau soi (); signifie en PHP?

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()?

EDIT

Si la classe est héritante, quelle classe pointe-t-elle?

103
user198729

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 se prolongent, 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 aurez:

object(MyChildClass)#1 (0) { } 

Ce qui signifie self signifie MyChildClass - 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 obtiendriez ce genre de sortie:

object(MyParentClass)#1 (0) { }

Ce qui signifie self signifie MyParentClass - c’est-à-dire ici aussi la classe dans laquelle il est écrit .




Avec PHP <5.3, cette "classe dans laquelle elle est écrite" est importante - et peut parfois causer des problèmes.

C'est pourquoi PHP 5.3 introduit un nouvel usage pour le mot clé static: il peut maintenant être utilisé exactement à l'endroit où nous avons utilisé self dans ces exemples:

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

}

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

Mais, avec static au lieu de self, vous obtenez maintenant:

object(MyChildClass)#1 (0) { } 

Ce qui signifie que static en quelque sorte pointe vers la classe utilisée (nous avons utilisé MyChildClass::getInstance()), et non celui dans lequel il est écrit.

Bien sûr, le comportement de self n'a pas été modifié pour ne pas casser les applications existantes - PHP 5.3 vient d'ajouter un nouveau comportement, en recyclant le mot clé static .


Et en parlant de PHP 5.3, vous voudrez peut-être jeter un coup d’œil à la page Liaisons statiques tardives de la PHP manuel.

199
Pascal MARTIN

Cela semble être une implémentation du motif Singleton . La fonction est appelée de manière statique et vérifie si la classe statique a la variable $_instance Définie.

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 une seule et même instance de classe à chaque appel, ce qui correspond au point du modèle singleton.

Je n'ai jamais vu cela se faire de cette façon, et honnêtement, je ne savais pas que c'était possible. Qu'est-ce que $_instance Est déclaré comme dans la classe?

9
Pekka 웃

Ceci est très probablement utilisé dans un modèle de conception singleton, dans lequel le constructeur est défini comme privé afin d'éviter toute instanciation, l'opérateur [deux = deux-points (::)] Peut accéder aux membres déclarés statiques dans la classe. membres, la pseudo-variable $ this ne peut pas être utilisée, d’où le code utilisé à la place, les singletons sont de bonnes pratiques de programmation qui autoriseront seulement 1 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 seul point d'accès. Dans ce cas, il l'a nommée getInstance(). Le getInstance en lui-même était la fonction qui créait l'objet à l'aide du nouveau mot clé à créer. un objet signifiant que la méthode constructeur a également été appelée.

la ligne if(!isset(self::instance)) vérifie si un objet a déjà été créé, vous ne pourriez pas le comprendre car le code est juste 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 eu accès à ce membre simplement

$this->_instance = 'something';

mais sa statique déclarée et donc nous ne pourrions pas utiliser le $ ce code que nous utilisons à la place

self::$_instance

en vérifiant si un objet est stocké dans cette variable de classe statique, la classe peut ensuite décider de créer ou non une seule instance. Par conséquent, si elle n'est pas définie,! isset, ce qui signifie qu'aucun objet n'existe sur le membre statique $ _instance, puis il génère un nouvel objet, le stocke dans le membre statique $_instance par la commande

self::$_instance = new self();

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

$thisObject = className::getInstance();

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

7
flimh

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

2
Matteo Riva

Si la classe est héritée, l'appel de getInstance () à partir de l'enfant ne vous donnera pas d'instance d'enfant. Il ne retournera qu'une instance d'instance parent. C'est parce que nous appelons new self ().

Si vous voulez que la classe enfant retourne une instance de classe enfant, utilisez new static () dans la méthode getInstance (), qui retournera ensuite l'instance de la classe enfant. Ceci s'appelle la liaison tardive !!

0
kta