Unveränderlichkeit (Immutability)
Kurz: Ein unveränderliches (immutables) Objekt kann nach seiner Erzeugung nicht mehr geändert werden. Statt es zu modifizieren, erzeugt man eine neue, angepasste Kopie.
Genauer: Unveränderliche Daten verhindern ganze Fehlerklassen: Niemand kann ein Objekt „hinter dem Rücken“ ändern, und mehrere Threads dürfen es ohne Sperren gleichzeitig lesen. Strings sind in Java, Python, C# und JavaScript unveränderlich; viele Sprachen bieten unveränderliche Sammlungen (Tupel, record, const, val, frozen).
Im Detail
name = "Mia"
neu = name.upper() # neuer String; "Mia" bleibt unverändert
punkt = (3, 4) # Tupel: unveränderlich
# punkt[0] = 5 # TypeError
from dataclasses import dataclass, replace
@dataclass(frozen=True)
class Person:
name: str
alter: int
p = Person("Mia", 17)
q = replace(p, alter=18) # Kopie mit geänderter Eigenschaft
print(p, q)const konfig = Object.freeze({ port: 8080, debug: false });
const neu = { ...konfig, debug: true }; // Kopie mit Änderung
const liste = [1, 2, 3];
const erweitert = [...liste, 4]; // liste bleibt [1, 2, 3]public record Punkt(int x, int y) {} // Felder sind finalVor- und Nachteile
| Vorteile | Nachteile |
|---|---|
| keine versehentlichen Änderungen | Kopieren kostet Zeit und Speicher |
| thread-sicher ohne Sperren | etwas mehr Schreibaufwand |
| einfach zu testen und nachzuvollziehen | bei sehr großen Daten braucht man persistente Datenstrukturen |
Persistente Datenstrukturen (Clojure, Scala, Immutable.js) teilen unveränderte Teile zwischen Versionen und machen Kopien billig. Verwandt sind const/final: Sie schützen nur die Variable, nicht unbedingt das Objekt dahinter (eine const-Liste in JavaScript darf weiterhin wachsen).
Siehe auch: Pure Function, Thread, Konstanten, Strings