MWCodebymw.de ↗
Kotlin

data class in Kotlin – copy(), Destrukturierung und warum ich sie ständig nutze

Ein `data class` ist mehr als ein Container für Felder. Du bekommst equals(), hashCode(), toString(), copy() und Destrukturierung geschenkt – und arbeitest damit sauber mit unveränderlichen Objekten. Ich zeige dir die Teile, die im Alltag wirklich zählen.

In fast jeder App, die ich baue, gibt es kleine Datenhalter: ein Nutzerprofil, ein Warenkorb-Eintrag, ein UI-Zustand. Dafür schreibe ich fast nie eine normale Klasse, sondern eine data class – die schenkt mir jede Menge Boilerplate, den ich sonst von Hand tippen (und pflegen) müsste.

Was du geschenkt bekommst

data class User(val name: String, val age: Int)

val a = User("Mia", 30)
val b = User("Mia", 30)

println(a)          // User(name=Mia, age=30)   ← lesbares toString()
println(a == b)     // true                     ← equals() vergleicht die Werte
println(a.hashCode() == b.hashCode()) // true    ← passend zu equals()

Bei einer normalen Klasse wäre a == b false (Referenzvergleich). Eine data class vergleicht dagegen inhaltlich – genau das, was man bei Daten fast immer will. Deshalb funktionieren sie auch als Set-Elemente oder Map-Schlüssel korrekt.

copy() – ändern, ohne das Original anzufassen

Der Teil, den ich am häufigsten brauche: Ich halte meine Objekte unveränderlich (val) und erzeuge bei einer Änderung eine neue Kopie mit copy().

val user = User("Mia", 30)
val geburtstag = user.copy(age = 31)   // nur age wird ersetzt

println(user)        // User(name=Mia, age=30)   ← unverändert
println(geburtstag)  // User(name=Mia, age=31)

Das ist die Grundlage für sauberes State-Management (etwa in einem ViewModel mit Compose): Der alte Zustand bleibt, du produzierst einen neuen. Kein versehentliches Mutieren von Objekten, die woanders noch benutzt werden.

Destrukturierung – Felder direkt entpacken

val (name, age) = user
println("$name ist $age")   // Mia ist 30

Praktisch in Schleifen über Paare oder Map-Einträge:

for ((id, punkte) in scores) {
    println("Spieler $id hat $punkte Punkte")
}

Die Reihenfolge zählt: Destrukturierung geht nach der Position der Konstruktor-Parameter, nicht nach dem Namen. Ordnest du die Parameter um, ändert sich also auch das Entpacken.

Eine Warnung zum Schluss

equals(), copy() & Co. betrachten nur die Properties im primären Konstruktor. Ein Feld, das du erst im Klassenrumpf deklarierst (val extra = …), fließt nicht in equals()/copy() ein. Wenn ein Wert zur Identität gehört, muss er in den Konstruktor.

Wenn du eine Android-App in Kotlin planst und Wert auf sauberen, wartbaren Code legst, setze ich das gern für dich um – schreib mir über bymw.de.

Quellen

#Kotlin#data class#copy#Destrukturierung#Immutability

Du brauchst mehr als ein Snippet?

Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →