In Kotlin versteht man unter Unveränderlichkeit in der Regel die Unmöglichkeit, den Zustand eines Objekts nach seiner Erstellung zu ändern. Dies wird durch die Verwendung von val (unveränderlichen) Eigenschaften sowie durch die Erstellung von Klassen erreicht, die nur im Konstruktor initialisiert werden, ohne Methoden, die es ermöglichen, interne Daten zu ändern.
Kotlin bietet im Gegensatz zu Java einen bequemen Mechanismus zur Erstellung von unveränderlichen Klassen über data class und Sammlungen wie List, Set, Map (die standardmäßig unveränderlich sind). Es ist jedoch wichtig zu verstehen, dass die grundlegenden Sammlungen in Kotlin nur auf der Ebene des Interfaces unveränderlich sind und das Objekt der Sammlung selbst geändert werden kann, wenn es in MutableList und ähnliches umgewandelt wird.
Beispiel für richtige Unveränderlichkeit:
// Data class und val gewährleisten Unveränderlichkeit data class User(val name: String, val age: Int) val user = User(name = "Ivan", age = 30) // user.name = "Sergey" // KOMPILIERFEHLER
Beispiel für Code mit Verletzung der Unveränderlichkeit:
class User(var name: String, var age: Int) val user = User("Ivan", 30) user.name = "Sergey" // Objektänderung ist möglich
Nuancen:
val-Eigenschaften garantiert keine vollständige Unveränderlichkeit, wenn die Eigenschaften referenzielle Typen sind und ihr interner Zustand geändert wird.val + unveränderliche Typen (zum Beispiel val scores: List<Int>).Sind Objekte einer data class mit nur val-Eigenschaften vollständig unveränderlich (immutable)?
Antwort: Nein, wenn die Eigenschaften veränderbare Objekte sind (zum Beispiel val items: MutableList<Int>), kann der interne Zustand geändert werden.
Beispiel:
data class Group(val members: MutableList<String>) val group = Group(mutableListOf("Tom", "Jerry")) group.members.add("Spike") // interner Zustand ändert sich
Geschichte
Im Projekt wurde ein unveränderliches
data classmitval-Eigenschaft vom TypMutableListverwendet. Einer der Entwickler erwartete, dass das Objekt nicht verändert werden kann, jedoch fügte ein anderer Entwickler neue Elemente zur Sammlung hinzu. Dies führte zu Inkonsistenzen der Daten und schwer fassbaren Bugs, als zwei Threads parallel dieselbe Liste änderten.
Geschichte
Bei der Übertragung einer Instanz der Klasse mit einer veränderbaren Sammlung zwischen den Schichten der Anwendung änderte eine Schicht den Inhalt, wobei die andere Schicht nicht benachrichtigt wurde. Dies führte zu Situationen, in denen die UI nicht über die vorgenommenen Änderungen informiert war und mit ungültigen Ausgangsdaten arbeitete.
Geschichte
Ein Entwickler war fälschlicherweise der Ansicht, dass
Listin Kotlin immer unveränderlich ist. Tatsächlich wurde im Hintergrund eine Implementierung verwendet, die aus Java (ArrayList) übergeben wurde, und der Versuch, die Liste zu ändern, führte zu unerwartetem Datenverlust und Bugs bei der Arbeit mit der Datenbank.