537 votes

Nouveau soi vs. nouveau statique

Je suis en train de convertir une bibliothèque PHP 5.3 pour qu'elle fonctionne avec PHP 5.2. La principale difficulté réside dans l'utilisation de liaisons statiques tardives telles que return new static($options); si je convertis cela en return new self($options) Est-ce que j'obtiendrai les mêmes résultats ?

Quelle est la différence entre new self y new static ?

956voto

BoltClock Points 249668

obtiendrai-je les mêmes résultats ?

Pas vraiment. Je ne connais pas de solution de contournement pour PHP 5.2, cependant.

Quelle est la différence entre new self y new static ?

self se réfère à la même classe dans laquelle le new le mot-clé est réellement écrit.

static dans les liaisons statiques de PHP 5.3, fait référence à la classe dans la hiérarchie sur laquelle vous avez appelé la méthode.

Dans l'exemple suivant, B hérite des deux méthodes de A . Le site self est liée à A car il est défini dans A de la première méthode, tandis que static est lié à la classe appelée (voir aussi get_called_class() ).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

0 votes

A du sens. Je pense que la meilleure solution est de passer le nom de la classe à la fonction qui utilise la liaison statique tardive, puis de retourner new $className($options) ;

12 votes

Vous n'avez pas besoin de "passer" le nom de la classe, vous pouvez toujours faire get_called_class() ce qui revient à dire que __CLASS__ mais compatible LSB.

7 votes

Get_called_class n'existe pas dans <PHP5.3. Par conséquent, si vous voulez obtenir le nom de la classe de l'objet instancié en PHP5.2, cette fonction n'est pas utile lorsque vous essayez de convertir une bibliothèque de PHP 5.3 en PHP 5.2.

24voto

barius Points 1484

Si la méthode de ce code n'est pas statique, vous pouvez obtenir une solution de contournement en 5.2 en utilisant get_class($this) .

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Les résultats :

string(1) "B"
string(1) "B"

19 votes

Si la méthode n'est pas statique, les liaisons statiques tardives deviennent totalement inutiles.

1 votes

Par exemple, vous pouvez l'utiliser dans la méthode "copy", où l'objet est copié sans utiliser l'option clone mais simplement en recréant et en définissant les propriétés. $copy = new static(); $copy->set($this->get()); return $copy;

9 votes

@BoltClock Certainement pas ? Si vous appelez une méthode statique surchargée à partir d'une méthode d'instance d'une sous-classe, alors votre choix de self:: o static:: va affecter l'utilisation de la version de la classe de base ou de la sous-classe de cette méthode statique. En l'absence de raison de penser qu'une telle situation indique intrinsèquement une mauvaise pratique (et je ne vois pas de raison pour laquelle ce devrait être le cas), le choix entre self:: y static:: est tout aussi pertinent dans les méthodes non statiques que dans les méthodes statiques. Ai-je mal compris votre commentaire, ou est-ce que l'un d'entre nous a tout simplement tort ?

8voto

FatalError Points 490

En plus des réponses des autres :

static: : sera calculée en utilisant les informations du temps d'exécution.

Cela signifie que vous ne pouvez pas utiliser static:: dans une propriété de classe parce que les valeurs des propriétés :

Doit pouvoir être évalué au moment de la compilation et ne doit pas dépendre d'informations au moment de l'exécution.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Utilisation de self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Veuillez noter que le commentaire "Fatal error" dans le code que j'ai fait n'indique pas où l'erreur s'est produite, l'erreur s'est produite plus tôt, avant que l'objet ne soit instancié, comme @Grapestain l'a mentionné dans les commentaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X