Sommaire
Les classes et les objets
Les classes : class
extends : héritage
Constructor : constructeur
Opérateur ::
parent
Sauvegarde d'objets - cas des sessions
Les fonctions magiques __sleep et __wakeup
Références dans un constructeur
|
4.7.8 Références dans un constructeur
Créer des références dans un constructeur peut conduire à
des résultats étranges. Ce tutorial vous guide pour éviter ces
problèmes.
|
<?php class foo { function foo($name) { // crée une référence dans le tableau global $globalref global $globalref; $globalref[] = &$this; // donne le nom de la variable $this->setName($name); // et l'affiche $this->echoName(); } function echoName() { echo "<br>",$this->Name; } function setName($name) { $this->Name = $name; } } ?>
|
Vérifions maintenant qu'il y a une différence entre $bar1
qui a été créé avec = et $bar2 qui a été
créé avec l'opérateur de référence =& :
|
<?php $bar1 = new foo('crée dans le constructeur'); $bar1->echoName(); $globalref[0]->echoName(); /* affiche : crée dans le constructeur crée dans le constructeur crée dans le constructeur */ $bar2 =&new foo('crée dans le constructeur'); $bar2->echoName(); $globalref[1]->echoName(); /* affiche : crée dans le constructeur crée dans le constructeur crée dans le constructeur */ ?>
|
Apparament, il n'y a pas de différence, mais en fait, il y en a une
significative : $bar1 et $globalref[0]
ne sont pas référencées, ces deux variables sont différentes.
Cela est du au fait que l'opérateur "new"ne retourne par de référence,
mais retourne une copie.
Note |
Il n'y a aucune perte de performance (puisque PHP 4 utilise un compteur de
référence) à retourner des copies au lieu de références. Au contraire, il est
souvent mieux de travailler sur les copies plutôt que sur les références,
car créer une référence prend un peu plus de temps que de créer une copie
qui ne prend virtuellement pas de temps (à moins de créer un
tableau géant ou un objet monstreux, auquel cas il est
préférable de passer par des références).
|
Pour prouver ceci, regardez le code suivant :
|
<?php // maintenant, nous allons changer de nom. Qu'attendez-vous? // Vous pouvez vous attendre à ce que les deux variables $bar // et $globalref[0] changent de nom... $bar1->setName('modifié'); // comme prédit, ce n'est pas le cas $bar1->echoName(); $globalref[0]->echoName(); /* affiche : crée dans le constructeur modifié */ // quelle est la différence entre $bar2 et $globalref[1] $bar2->setName('modifié'); // Heureusement, elles sont non seulement égales, mais // elles représentent la même variable. // donc $bar2->Name et $globalref[1]->Name sont les mêmes $bar2->echoName(); $globalref[1]->echoName(); /* affiche : modifié modifié */ ?>
|
Un dernier exemple pour bien comprendre.
|
<?php class a { function a($i) { $this->value = $i; // Essayez de comprendre on n'a pas besoin de // référence ici $this->b = new b($this); } function createRef() { $this->c = new b($this); } function echoValue() { echo "<br>","class ",get_class($this),': ',$this->value; } } class b { function b(&$a) { $this->a = &$a; } function echoValue() { echo "<br>","class ",get_class($this),': ',$this->a->value; } } // Essayez de comprendre pourquoi une copie simple va // conduire à un résultat indésirable à // la ligne marquée d'une étoile $a =&new a(10); $a->createRef(); $a->echoValue(); $a->b->echoValue(); $a->c->echoValue(); $a->value = 11; $a->echoValue(); $a->b->echoValue(); // * $a->c->echoValue(); /* output: class a: 10 class b: 10 class b: 10 class a: 11 class b: 11 class b: 11 */ ?>
|
|