Le clonage d'objets consiste à copier un objet source vers un objet cible.
Mais ce clonage peut être accompli superficiellement, c'est-à-dire que la référence de l'objet source est transmise à l'objet cible. Cela entraîne que les deux objets pointent vers le même contenu.
//Copie superficielle objet A référence_A --> contenu_A objet B référence_A --> contenu_A
Dans ce cas, les modifications apportées dans l'objet A seront répercutées dans l'objet B.
Objet A = Jean Clonage de Objet A vers Objet B Objet B ( = Jean) //Réaffectation Objet A = Pierre //Etat de l'objet cible Objet B ( = Pierre)
Un autre type de clonage est possible, il s'agit de copier l'état d'un objet source vers un autre objet.
//Copie profonde objet A référence_A --> contenu_A objet B référence_B --> contenu_A
De cette manière, la modification de l'un des objets impliqués dans le clonage, ne se répercute pas sur l'autre objet.
Objet A = Jean Clonage de Objet A vers Objet B Objet B ( = Jean) //Réaffectation Objet A = Pierre //Etat de l'objet cible Objet B ( = Jean)
Par défaut, PHP 5 fait une copie systématique des propriétés de l'objet source, vers l'objet cible. Ceci a pour conséquence un clonage profond des objets, soit une copie des valeurs des propriétés de l'objet source vers l'objet cible, tant que les propriétés de l'objet source ne sont pas des objets. En effet, dans le cas des propriétés instances d'une classe quelconque, la copie est alors superficielle, c'est à dire une transmission des références d'objet des propriétés vers l'objet cible.
Objet A = Pierre, Dupont Clonage de Objet A vers Objet B Objet B ( = Pierre, Dupont) //Réaffectation Objet A = Jean, Dupont //Etat de l'objet cible Objet B ( = Pierre, Dupont) Objet Prenom = Pierre Objet Nom = Dupont Objet A = Objet Prenom, Objet Nom Clonage de Objet A vers Objet B Objet B ( = Objet Prenom ( = Pierre), Objet Nom ( = Dupont)) //Réaffectation de l'objet Prenom Objet A -> Objet Prenom = Jean //Etat de l'objet cible Objet B ( = Objet Prenom ( = Jean), Objet Nom ( = Dupont))
L'appel de la fonction clone produit le clonage d'un objet source vers un objet cible dans les conditions précitées.
$Objet_Cible = clone $Objet_Source;
La redéfinition de la méthode __clone() permet d'obtenir un comportement plus approprié pour le clonage d'un objet source. Il devient possible d'obtenir un objet cible indépendant de l'objet source, mais en conservant l'état et le comportement de ce dernier. Avec ce type de clonage, la modification de l'état de l'un des objets, n'entraîne pas de changement dans l'autre.
class UneClasse { //... public function __clone(){ //Bloc de code } }
Chaque objet possède une méthode __clone() par défaut, qui effectue une copie superficielle de toutes les propriétés de l'objet source vrs l'objet cible.
Exemple [voir]//Clonage simple <html> <body> <?php class Personne { static $compteur; private $date_inscription; private $date_modification; private $id; private $civilite; private $nom; private $prenom; private $adresse; private $telephone; public function __construct( $civilite, $nom, $prenom, $adresse, $telephone){ $this->date_inscription = date('d M Y H:i:s'); $this->civilite = $civilite; $this->nom = $nom; $this->prenom = $prenom; $this->adresse = $adresse; $this->telephone = $telephone; $this->date_modification = $this->date_inscription; } public function __toString(){ return '[' . $this->civilite . ', ' . $this->nom . ', ' . $this->prenom . ', ' . $this->adresse . ', ' . $this->telephone . ']'; } public function setNom($nom){ $this->nom = $nom; $this->dateModif(); } public function setPrenom($prenom){ $this->prenom = $prenom; $this->dateModif(); } public function setAdresse($adresse){ $this->adresse = $adresse; $this->dateModif(); } public function setTelephone($telephone){ $this->telephone = $telephone; $this->dateModif(); } private function dateModif(){ $this->date_modification = date('d M Y H:i:s'); } } $personne = new Personne( 'Madame', 'Waldec', 'Anne', '75 rue Belleville 75010 Paris', '0142152432'); sleep(1); $clone = clone $personne; sleep(2); $personne->setNom('Walewski'); echo 'Original : '; echo $personne; echo '<br/>'; echo 'Clone : '; echo $clone; /* Original : [Madame, Walewski, Anne, 75 rue Belleville 75010 Paris, 0142152432] Clone : [Madame, Waldec, Anne, 75 rue Belleville 75010 Paris, 0142152432] */ echo '<br/>'; echo '<br/>'; print_r($personne); print_r($clone); ?> </body> </html> //Clonage avec redéfinition de la méthode __clone() <html> <body> <?php // Un object de gestion des chaines de caractères class Chaine { public $valeur; public function __construct(){ $this->valeur = func_get_arg(0); } public function set($valeur){ $this->valeur = $valeur; } public function get(){ return $this->valeur; } public function __toString(){ return '[' . $this->valeur . ']'; } } class Personne { static $compteur; private $date_inscription; private $date_modification; private $id; private $civilite; private $nom; private $prenom; private $adresse; private $telephone; public function __construct( $civilite, $nom, $prenom, $adresse, $telephone){ $this->date_inscription = new Chaine(date('d M Y H:i:s')); $this->civilite = new Chaine($civilite); $this->nom = new Chaine($nom); $this->prenom = new Chaine($prenom); $this->adresse = new Chaine($adresse); $this->telephone = new Chaine($telephone); $this->date_modification = new Chaine($this->date_inscription->get()); } public function __toString(){ return '[' . $this->civilite->get() . ', ' . $this->nom->get() . ', ' . $this->prenom->get() . ', ' . $this->adresse->get() . ', ' . $this->telephone->get() . ', ' . $this->date_inscription->get() . ', ' . $this->date_modification->get() . ']'; } public function setNom($nom){ $this->nom->set($nom); $this->dateModif(); } public function setPrenom($prenom){ $this->prenom->set($prenom); $this->dateModif(); } public function setAdresse($adresse){ $this->adresse->set($adresse); $this->dateModif(); } public function setTelephone($telephone){ $this->telephone->set($telephone); $this->dateModif(); } private function dateModif(){ $this->date_modification->set(date('d M Y H:i:s')); } public function __clone(){ $this->date_inscription = new Chaine(date('d M Y H:i:s')); $this->civilite = new Chaine($this->civilite->get()); $this->nom = new Chaine($this->nom->get()); $this->prenom = new Chaine($this->prenom->get()); $this->adresse = new Chaine($this->adresse->get()); $this->telephone = new Chaine($this->telephone->get()); $this->date_modification = new Chaine($this->date_inscription->get()); } } $personne = new Personne( 'Madame', 'Waldec', 'Anne', '75 rue Belleville 75010 Paris', '0142152432'); sleep(1); $clone = clone $personne; sleep(2); $personne->setNom('Walewski'); echo 'Original : '; echo $personne; echo '<br/>'; echo 'Clone : '; echo $clone; /* Original : [Madame, Walewski, Anne, 75 rue Belleville 75010 Paris, 0142152432, 26/Jul/2005 10:08:13, 26/Jul/2005 10:08:16] Clone : [Madame, Waldec, Anne, 75 rue Belleville 75010 Paris, 0142152432, 26/Jul/2005 10:08:14, 26/Jul/2005 10:08:14] */ echo '<br/>'; echo '<br/>'; print_r($personne); echo '<br/>'; print_r($clone); ?> </body> </html> |
Les invocations de la fonction sleep() ont pour but d'obtenir une différence de date entre l'instanciation de l'objet source et le clonage de ce dernier ver l'objet cible.