Riferimenti all'interno del costruttore

La creazione di riferimenti con costruttori può condurre a risultati confusi. Questa sezione in stile Tutorial vi aiuterà ad evitare problemi.

<?php
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 =& ...

<?php
$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).

Per dimostrare quello che è scritto sopra guardate il codice qui sotto.

<?php
// 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.

<?php
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
*/
?>

Hosting by: hurra.com
Generated: 2007-01-26 17:56:36