Après avoir lu ton post ce matin, j'y ai réfléchi en allant en cours, et pour moi ce concept de const n'est pas applicable.
En fait, 2 possibilités:
- soit le const est un modifieur d'une variable, exactement comme final
Il y a ici un gros problème, c'est que le mot-clé const s'applique à une variable (donc à une référence), alors que le concept (l'immutabilité) s'applique sur l'instance de l'objet.
Ainsi, tu peux faire:
1 2 3
| const UnObjet o = new UnObjet();
UnObjet o2 = o;
o2.methodeQuiModifie(); |
Une solution serait d'interdire l'affectation d'une variable const vers une non const, mais aussi d'une non const vers une const (car il faut soit que toutes les références soient const, soit qu'elles soient toutes non const).
Mais là cela pose des problèmes. Imagine tu as une méthode qui prend en paramètre une instance de type UnObjet. Déjà ce qui est passée est une copie de la référence, donc il faut que le compilateur sache que c'était une const. Mais admettons.
1 2 3
| public static void methode(UnObjet o) {
o.methodeQuiModifie();
} |
1 2
| const UnObjet o = new UnObjet();
methode(o); // ne marche pas, car o est const, et la méthode attend un non const |
et inversement:
1 2 3
| public static void methode2(const UnObjet o) {
o.uneMethode();
} |
1 2
| UnObjet o = new UnObjet();
methode2(o); //ne marche pas, l'objet doit être constant |
Ceci est quand même très embêtant.
De plus, si une variable est déclarée const, il serait impossible de créer un objet const sans l'affecter à une variable.
new const UnObjet(); //pourquoi pas? pas terrible quand même...
Donc cette première solution est incohérente, car le mot-clé const s'applique à une variable (donc à une référence), alors que le concept (l'immutabilité) s'applique sur l'instance de l'objet.
- soit const serait un modifieur de classe, pour faire par exemple:
public const class UneClasse {...}
Ceci permettrait de vérifier l'immutabilité à la compilation.
On se pose alors la question, comment vérifier l'immutabilité à la compilation?
- il faut vérifier récursivement que les attributs de type primitifs sont finaux, et que les attributs références sont soit finaux, soit constants.
Pour les finaux, c'est facile.
Pour les constants, on a vu dans le premier point que const ne devait pas s'appliquer à une variable, donc il faudrait que la classe de chacun des attributs soit const (immutable).
Or, avec le pattern immutable, on peut avoir des composants mutables tout en garantissant une classe immutable.
par exemple:
1 2 3 4 5 6 7 8 9 10 11 12
| public class Immutable {
private Point point;
public Immutable(int x, int y) {
point = new Point(x,y);
}
public int getX() {
return point.getX();
}
public int getY() {
return point.getY();
}
} |
Une solution pourrait être de vérifier que les attributs de type non const ne soit jamais affectés à partir d'un paramètre, et qu'il n'y a pas de getter dessus... (récursivement!)
(en y réfléchissant, pourquoi pas)
Voilà pourquoi je pense que ça ne serait finalement pas une avancée aussi intéressante qu'il n'y parait...
Sans parler de la compatibilité ascendante, des classes qui sont immutables par le pattern, qui devraient être composées dans des classes "const" alors qu'elles ne sont elles-même pas const (bien qu'immutable).
Pour prendre un peu de recul, si on introduit un mot-clé (du moins son utilisation, car il existe déjà sans être utilisé) pour un design-pattern, pourquoi ne pas introduire également d'autres mots-clés : singleton, listener...
public singleton class MonSingleton { ... }
...
Partager