Aller au contenu

Les variables immuables

🤖 Rédaction assistée par IA.

Définition

Une variable est dite immuable si ni la variable, ni sa valeur ne peuvent être modifiées après l'initialisation (ex : tuple en Python, chaînes de caractères en Java et en Python).

Intérêt

  • Il est inutile de copier des variables immuables pour se protéger contre des modifications dans d'autres parties du programme.
  • Il n'y a pas de risque lié aux accès concurrents en cas de parallélisation des traitements.
  • Le code est plus facile à suivre : la valeur d'une variable immuable est connue dès sa déclaration.

En pratique

Nous trouverons des variantes en fonction des langages de programmation.

Les types immuables

Certains types sont immuables par nature en fonction du langage. Par exemple, les chaînes de caractères sont immuables en Java (String), en JavaScript et TypeScript (string) ou en Python (str) : les méthodes telles toUpperCase() renvoient une nouvelle chaîne.

À l'inverse, une std::string est modifiable en C++ (ex : s[0] = 'A';).

Rendre une variable immuable

La méthode pour rendre une variable immuable varie d'un langage à l'autre :

const ages: number[] = [20, 21];
ages.push(22); // autorisé : le contenu est modifié
// ages = []; // erreur : réassignation interdite

const frozen: readonly number[] = [20, 21];
// frozen.push(22); // erreur : tableau en lecture seule
final List<Integer> ages = new ArrayList<>(List.of(20, 21));
ages.add(22); // autorisé : le contenu est modifié
// ages = new ArrayList<>(); // erreur de compilation : réassignation interdite

final List<Integer> frozen = List.of(20, 21);
// frozen.add(22); // UnsupportedOperationException à l'exécution
from typing import Final

AGES: Final = [20, 21]
AGES.append(22)  # autorisé : le contenu est modifié
# AGES = []  # signalé par mypy, mais accepté à l'exécution

FROZEN = (20, 21)  # tuple : valeur immuable
# FROZEN[0] = 0  # TypeError
std::vector<int> ages{20, 21};
ages.push_back(22); // autorisé

const std::vector<int> frozen{20, 21};
// frozen.push_back(22); // erreur de compilation : objet constant
const AGES = [20, 21]; // constante : ni réassignable, ni modifiable

final class Person
{
    public function __construct(public readonly int $age) // PHP >= 8.1
    {
    }
}

$person = new Person(20);
// $person->age = 21; // Error : propriété en lecture seule

L'immuabilité par défaut

Certains langages rendent les variables immuables par défaut et disposent d'un mot clé spécifique pour les rendre modifiables. C'est le cas de Rust avec mut :

let age = 20;
// age = 21; // erreur : cannot assign twice to immutable variable

let mut count = 0;
count += 1; // autorisé

Mise en garde

Il ne faut pas confondre une variable immuable avec une variable non réassignable (ex : const en JavaScript, final en Java) : cette dernière ne peut pas recevoir une nouvelle valeur, mais le contenu de la valeur référencée peut rester modifiable (ex : const sur un tableau en JavaScript). Il s'agit alors d'une immuabilité superficielle.

Pour garantir qu'un objet ne sera pas modifié, il faudra concevoir des objets immuables (voir La programmation orientée objet).

Liens utiles