Une classe ou variable est dite immuable, s’il n’est pas possible d’aller changer ses valeurs.
Il est mieux d'opter pour l'immuabilité en créant une classe
Quand on fait une classe immuable, il est bien d’avoir des fonctions qui retournent une nouvelle instance de cette classe, en changeant des attributs
Exemple -- Deux dates semblables dont seul l'année change
Une classe immuable est toujours non-modifiable, mais l’inverse n’est pas vrai.
Une classe non-modifiable peut ne pas être immuable.
Définition d’une classe immuable
Tous les attributs de la classe sont finaux et initialisés lors de la construction.
Toute valeur non-immuable est copiée avant d’être stockée dans une variable (pour éviter que nous pointions à une référence qui peut être une variable modifiable)
Chaque variable qui est passée en tant que référence (structures complexes), implique que sont getter respectif ne fournisse qu’une copie de cette variable.
Tableaux immuables
Les tableaux en java sont par définition modifiables, et donc non-immuables. Il est cependant possible d’avoir des listes non modifiables, via la fonction Collections.unmodifiableList(array)
Pour stocker des tableaux dans des classe immuables, il faut donc ainsi les rendre non-modifiables via la fonction unmodifiableList
Il est aussi possible de copier une liste via la fonction List.copyOf()
Bâtisseurs
Il est cependant possible qu’une classe que l’on veut qu’elle soit immuable ait beaucoup trop d’attributs à définir. Pour rendre son instanciation plus agréable, on peut faire appel à la notion des Bâtisseurs (Builder en anglais)
Un bâtisseur se retourne lui même suite à chaque fonction, afin de pouvoir l’utiliser de multiples fois avant de construire l’objet, via une fonction build().
Exemple -- classe Builder
public final class DateBuilder { private int y, m, d; public DateBuilder(int y, int m, int d) { this.y = y; this.m = m; this.d = d; } public int year() { return y; } public void setYear(int y2) { y = y2; } // … idem pour month/setMonth et day/setDay // Il a donc des fonctions typiques de batisseur : public DateBuilder setYear(int y2) { y = y2; return this; } // idem pour setMonth, et setDay, etc... public Date build() { return new Date(y, m, d); }}
Le bâtisseur est immuable, mais ce n’est pas un problème car il construit une classe qui sera immuable, et le bâtisseur n’est utilisé que très brièvement
Ces classes sont souvent imbriquées dans la classe qu’ils construisent.
Règles des bâtisseurs
Nommer la classe ...Builder ou juste Builder
Imbriquer statiquement dans la classe qu’elle construit