La creazione di riferimenti con costruttori può condurre a risultati confusi. Questa sezione in stile Tutorial vi aiuterà ad evitare problemi.
class Foo { function Foo($name) { // crea un riferimento all'interno della variabile $globalref global $globalref; $globalref[] = &$this; // setta Name con il valore passato $this->setName($name); // e lo manda all'output $this->echoName(); } function echoName() { echo "<br>",$this->name; } function setName($name) { $this->name = $name; } } |
Verifichiamo se c'è una differenza fra $bar1 che è stato creato usando l'operatore = e $bar2 che è stato creato usando l'operatore di riferimento =& ...
$bar1 = new Foo('set in constructor'); $bar1->echoName(); $globalref[0]->echoName(); /* output: imposta nel costruttore imposta nel costruttore imposta nel costruttore */ $bar2 =& new Foo('set in constructor'); $bar2->echoName(); $globalref[1]->echoName(); /* output: imposta nel costruttore imposta nel costruttore imposta nel costruttore */ |
Apparentemente non c'è differenza, ed in effetti questo è molto significativo: $bar1 e $globalref[0] _ NON _ sono riferimenti, ma sono due variabili diverse. Questo succede perché "new" non restituisce per default un riferimento, ma restituisce una copia.
Nota: Non c'è perdita di prestazioni (da php 4 in su si usa il riferimento) ad istanziare copie per riferimento. Al contrario spesso è meglio lavorare con copie istanziate per riferimento, perché creare copie reali richiede un certo tempo, mentre creare riferimenti virtuali è immediato, (a meno che non si parli di un grande array o un oggetto che viene modificato in modo successivo, allora sarebbe saggio usare i riferimenti per cambiargli tutti i valori simultaneamente).
// ora cambieremo il nome che cosa vi aspettate? // potreste prevedere che $bar e $globalref[0] cambino i loro nomi ... $bar1->setName('set from outside'); // come accennato prima ecco il risultato. $bar1->echoName(); $globalref[0]->echoName(); /* output: set from outside set in constructor */ // vediamo le differenze tra $bar2 e $globalref[1] $bar2->setName('set from outside'); // fortunatamen sono solo uguali, ma sono la stessa variabile // $bar2->name e $globalref[1]->name sono la stessa cosa $bar2->echoName(); $globalref[1]->echoName(); /* output: set from outside set from outside */ |
Un esempio finale, prova a farvi capire.
class A { function A($i) { $this->value = $i; // provare a capire perchè qui non abbiamo bisogno d'un riferimento $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; } } // prova a capire perchè usando una semplice copia si avrebbe // in un risultato indesiderato nella riga segnata con * $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 */ |