L'aliasing peut souvent provoquer plus du mal que du bien dans une application. C'est pourquoi il faut l'utiliser avec précaution.
Logiquement, un alias ressemble à une nouvelle couverture pour quelque chose qui existe déjà. Cela s'applique aux aliases dans les noms de domaines. On peut par exemple avoir 4 adresses différentes qui sont ensuite redirigés vers un site commun. La même chose s'applique en Java.
Si l'on crée un alias pour un objet déjà existant, toutes les modifications de cet alias vont se répercuter sur l'objet initialement créé. Autrement dit, un alias n'est pas une nouvelle instance d'une classe. Il est une sorte de représentation d'un objet déjà initialisé. On peut constater cela sur cet exemple :
public class Aliases { public static void main(String[] args) { Cat cat1 = new Cat("cat1"); Cat cat2 = cat1; System.out.println("The first part"); System.out.println("cat1 name = " + cat1.getName()); System.out.println("cat2 name = " + cat2.getName()); cat2.setName("cat2"); System.out.println("The second part"); System.out.println("cat1 name = " + cat1.getName()); System.out.println("cat2 name = " + cat2.getName()); } } class Cat { private String name; public Cat(String n) { name = n; } public void setName(String n) { name = n; } public String getName() { return name; } }
Le résultat est :
The first part
cat1 name = cat1
cat2 name = cat1
The second part
cat1 name = cat2
cat2 name = cat2
On constate immédiatement que l'attribution du cat1 à Cat cat2 n'a pas créé une nouvelle instance de l'objet Cat. A la place de cela, il a créé un nouvel alias qui pointe vers l'instance conçue par Cat cat1 = new Cat("cat1").
En PHP, cela marchera de la même manière. La variable issue de l'alias deviendra alors un nouvel objet, indépendant du premier. Regardons cela sur un exemple :
$cat1 = new Cat("cat1"); $cat2 = $cat1; echo "The first part \n"; echo "cat1 name = ".$cat1->getName()." \n"; echo "cat2 name = ".$cat2->getName()." \n"; $cat2->setName("cat2"); echo "The second part \n"; echo "cat1 name = ".$cat1->getName()." \n"; echo "cat2 name = ".$cat2->getName()." \n"; class Cat { protected $name = ""; public function __construct($n) { $this->name = $n; } public function getName() { return $this->name; } public function setName($n) { $this->name = $n; } }
Et le résultat :
The first part
cat1 name = cat1
cat2 name = cat1
The second part
cat1 name = cat2
cat2 name = cat2
Cette confusion potentielle est la raison principale pour laquelle on devrait éviter des aliases au maximum. A leur place on devrait privilégier le clonage des objets. On peut l'achever grâce à la méthode clone() qui reprend l'objet tel quel et crée une nouvelle instance dans la mémoire. On peut constater cela sur l'exemple amélioré du début :
public class Aliases { public static void main(String[] args) { Cat cat1 = new Cat("cat1"); Cat cat2 = (Cat)cat1.clone(); System.out.println("The first part"); System.out.println("cat1 name = " + cat1.getName()); System.out.println("cat2 name = " + cat2.getName()); cat2.setName("cat2"); System.out.println("The second part"); System.out.println("cat1 name = " + cat1.getName()); System.out.println("cat2 name = " + cat2.getName()); } } class Cat implements Cloneable { private String name; public Cat(String n) { name = n; } public void setName(String n) { name = n; } public String getName() { return name; } public Object clone() { Object c = null; try { c = super.clone(); } catch(CloneNotSupportedException e) { System.err.println("An exception occured on cloning Cat instance" + e.getMessage()); } return c; } }
Voici le résultat :
The first part
cat1 name = cat1
cat2 name = cat1
The second part
cat1 name = cat1
cat2 name = cat2
Dans notre classe Cat on a rajouté une implémentation de l'interface Cloneable qui permet de copier les objets. Grâce à cela on a une possibilité de manipuler deux instances distinctes de la même classe.
Il faut donc avoir en tête qu'un alias n'est pas égal à une nouvelle instance de la classe. Et que pour la générer, il faut soit utiliser la méthode clone(), soit passer par son constructeur.