Una differenza molto importante presente in ogni linguaggio di programmazione è sicuramente quella che intercorre tra valore e riferimento. Come sappiamo, se si lavora con i valori si ha a che fare con vere e proprie "copie" dei dati, mentre se si stanno utilizzando i riferimenti, si ha a che fare con i dati veri e propri: eventuali modifiche influenzeranno le variabili o i dati reali.
Dalla versione 5 di PHP, gli oggetti non vengono più trattati per valore, ma per riferimento (in realtà, come spiegheremo tra qualche riga, più che riferimenti si tratta di copie dello stesso identificatore univoco). Questo, a parte tutte le migliorie interne al motore del linguaggio, implica che se si passa un oggetto ad una funzione o lo si assegna ad un'altra variabile, quello che verrà utilizzato sarà il suo riferimento e dunque l'oggetto verrà modificato. Di seguito troviamo degli esempi pratici che spiegano molto bene questo concetto. Partiamo dall'assegnazione di un oggetto con una variabile:
class MyClass {
public $a = 10;
}
$myClass_1 = new MyClass;
// assegnazione, ora entrambe le variabili si riferiscono allo stesso id univoco
$myClass_2 = $myClass_1;
// modifica
$myClass_2->a = 20;
// aggiunta
$myClass_2->b = 30;
// stampa 20
echo $myClass_1->a;
// stampa 30
echo $myClass_1->b;
Entrambe le variabili $myClass_1
e $myClass_2
si riferiscono alla stessa posizione, dunque eventuali modifiche o aggiunte ad una di esse si ripercuoteranno anche sull'altra. Vediamo ora il caso in cui passiamo gli oggetti come parametri delle funzioni:
class MyClass {
public $a = 10;
}
$myClass_1 = new MyClass;
// funzione che modifica gli oggetti
function editObj($obj) {
$obj->a = 20;
}
// chiamata
editObj($myClass_1);
// stampa 20
echo $myClass_1->a;
Anche in questo caso, ciò con cui si lavora è il riferimento e non il valore, dunque l'oggetto originale viene alterato.
Riferimento vs identificatore
Come ho dichiarato in precedenza, anche se il comportamento è pressoché identico, in realtà nel caso degli oggetti non si ha a che fare con veri e propri riferimenti, ma con copie dello stesso identificatore. Ogni variabile istanza possiede un identificatore univoco (che chiameremo id
): quando si assegna l'oggetto ad una nuova variabile o lo si passa ad una funzione, questo id verrà utilizzato come riferimento:
class MyClass {
// implementazione...
}
$a = new MyClass; // -id- assegnato
// ($a) = ($b) = -id-
$b = $a;
function editObj($obj) {
// ($obj) = ($a) = -id-
$obj->a = 20;
}
Ovviamente, anche con gli oggetti è possibile utilizzare il riferimento vero e proprio tramite l'operatore &
. In questo caso verrà utilizzato il riferimento stesso: entrambe le variabili si riferiranno alla stessa posizione:
$a = new MyClass; // -id- assegnato
// ($a, $b) = -id-
$b = $a;
Conclusione
Bisogna tenere sempre in mente che in PHP5 gli oggetti vengono trattati per riferimento: questo concetto è di vitale importanza per le nostre applicazioni. Gli sviluppatori che non provengono dalla versione 4 di PHP molto probabilmente troveranno questo comportamento a dir poco naturale ed "ovvio", mentre chi è abituato a trattare gli oggetti per valore dovrà svolgere qualche piccolo test per prendere confidenza con questo nuovo (e sicuramente migliore) stile di programmazione.