Come descritto nelle lezioni precedenti, dalla versione 5 di PHP in poi, gli oggetti vengono trattati per riferimento. In questa lezione, vedremo come lavorare con delle copie di oggetti (clonazione) invece che con dei riferimenti.
Assegnamento e clonazione
A partire da PHP 5, la copia di un oggetto, tramite assegnamento, è solo un riferimento, ciò avviene a differenza di quanto accadeva in PHP 4, dove l'assegnamento tra 2 oggetti creava una copia. A tal proposito è possibile formulare un semplice esempio:
<?php
// classe Person
class Person {
public $nome;
public $cognome;
}
// creazione nuovo oggetto Person
$personA = new Person();
$personA->nome="Giulia";
$personA->cognome="Q";
// assegnazione per riferimento
$personB = $personA;
// modifica di $personA
$personB->nome="Giuseppe";
var_dump($personA);
var_dump($personB);
?>
L'output generato dal codice proposto in precedenza sarà quindi il seguente:
object(Person)#1 (2) {
["nome"]=>
string(8) "Giuseppe"
["cognome"]=>
string(1) "Q"
}
object(Person)#1 (2) {
["nome"]=>
string(8) "Giuseppe"
["cognome"]=>
string(1) "Q"
}
Nell'esempio precedente, $personB
ha il riferimento di $personA
. Pertanto, quando un oggetto è assegnato come riferimento, le modifiche apportate ad uno di essi si riflettono anche sugli altri. Se invece volessimo lavorare con delle copie, e non con dei riferimenti, potremmo utilizzare la funzione clone
. Per clonare un oggetto è sufficiente impiegare la parola chiave clone
dopo l'operatore di assegnazione =
.
...
$obj2 = clone $obj1;
...
Questa funzione nativa crea automaticamente una nuova istanza dell'oggetto con le relative copie delle proprietà; si tratta di una copia precisa e indipendente dell'altro oggetto, dove eventuali aggiunte o modifiche al clone non incideranno sull'originale. Anche un questo caso è possibile proporre un breve esempio:
<?php
// creazione nuovo oggetto Person
$personA = new Person();
$personA->nome="Giulia";
$personA->cognome="Q";
// assegnamento con clonazione
$personB = clone $personA;
$personB->nome="Giuseppe";
var_dump($personA);
var_dump($personB);
?>
L'output generato sarà dunque il seguente:
object(Person)#1 (2) {
["nome"]=>
string(6) "Giulia"
["cognome"]=>
string(1) "Q"
}
object(Person)#2 (2) {
["nome"]=>
string(8) "Giuseppe"
["cognome"]=>
string(1) "Q"
}
Metodo magico __clone
Il metodo __clone
, è un metodo magico, il quale fornisce tutte le funzionalità per la clonazione completa e indipendente di un oggetto, esso crea un nuovo oggetto identico all'originale copiando tutte le variabili membro.
Supponiamo di voler modificare la proprietà $azienda
della classe Person
in caso di clonazione dell'oggetto come nell'esempio proposto di seguito:
<?php
class Person {
public $nome;
public $cognome;
public $azienda;
// aggiunta all'interno della definizione della classe del metodo __clone().
public function __clone(){
// associazione
$this->azienda = "Warner Bros.";
}
}
class Azienda {
public $nomeAzienda;
}
$aziendaA = new Azienda();
$aziendaA->nomeAzienda="Html.it";
$person1 = new Person();
$person1->nome="Giulia";
$person1->cognome="Q";
$person1->azienda= $aziendaA;
$person3 = clone $person1;
$person3->nome="Giuseppe";
var_dump($person1);
var_dump($person3);
?>
Non appena PHP eseguirà la clonazione del nuovo oggetto, verrà invocato il metodo __clone()
e l'oggetto clonato sarà accessibile, nel rispetto del principio di incapsulamento, mediante la variabile $this
. In questo caso $person3->azienda
sarà uguale a "Warner Bros." perché il metodo __clone()
verrà chiamato solo per l'oggetto $person3
settando il valore di $this->azienda
in questo modo. Di seguito l'output generato in fase di esecuzione:
object(Person)#2 (3) {
["nome"]=>
string(6) "Giulia"
["cognome"]=>
string(1) "Q"
["azienda"]=>
object(Azienda)#1 (1) {
["nomeAzienda"]=>
string(7) "Html.it"
}
object(Person)#3 (3) {
["nome"]=>
string(8) "Giuseppe"
["cognome"]=>
string(1) "Q"
["azienda"]=>
string(12) "Warner Bros."
}
Ora che sono state descritte le procedure per clonare un oggetto e personalizzare la funzione di clonazione sarà possibile creare oggetti normali per riferimento oppure clonarli, realizzando delle copie vere e proprie.