Android Academy · Lektion

Data classes og sealed classes

Brug data classes til værdibaseret lighed og copy(), og sealed classes til komplette typehierarkier og tydelig modellering af tilstande.

Lektion 3 af 413 trin

Data classes og sealed classes er en gratis Android Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Android Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Android Academy-kurset indeholder 4 lektioner i alt.

Hvad er dataklasser?

En dataklasse i Kotlin er en klasse, hvis primære formål er at indeholde data. Compileren genererer automatisk nyttige metoder for dig:

  • equals() — sammenlign to instanser efter værdi
  • hashCode() — en konsistent hash baseret på egenskaberne
  • toString() — en læsbar strengrepræsentation
  • copy() — opret en ændret kopi
  • Understøttelse af destrukturering

Deklaration af en dataklasse

Tilføj nøgleordet data før class. Alle egenskaber skal være i den primære konstruktør:

data class User(val id: Int, val name: String, val email: String)

fun main() {
    val u1 = User(1, "Alice", "alice@example.com")
    val u2 = User(1, "Alice", "alice@example.com")

    println(u1)          // User(id=1, name=Alice, email=alice@example.com)
    println(u1 == u2)    // true  (value equality)
    println(u1 === u2)   // false (different objects)
}

copy() — ændr ét felt

copy() opretter en ny instans med nogle ændrede egenskaber. Den oprindelige instans ændres ikke (uforanderlighed):

data class Product(val name: String, val price: Double, val inStock: Boolean)

fun main() {
    val original = Product("Laptop", 999.0, true)

    // Only change the price; keep everything else
    val onSale = original.copy(price = 799.0)

    println(original)  // Product(name=Laptop, price=999.0, inStock=true)
    println(onSale)    // Product(name=Laptop, price=799.0, inStock=true)
}

Destrukturerende deklarationer

Dataklasser understøtter destrukturering — pak egenskaber ud i variabler ved hjælp af componentN()-funktioner, som compileren genererer:

data class Point(val x: Int, val y: Int)

fun main() {
    val point = Point(10, 20)

    // Destructure into separate variables
    val (x, y) = point
    println("x=$x, y=$y")   // x=10, y=20

    // Also works in for loops with maps
    val scores = mapOf("Alice" to 95, "Bob" to 88)
    for ((name, score) in scores) {
        println("$name: $score")
    }
}

Hvad er forseglede klasser?

En forseglet klasse er et begrænset klassehierarki — alle underklasser skal defineres i den samme fil. Det gør mængden af mulige typer kendt på kompileringstidspunktet.

Brug forseglede klasser til at repræsentere en begrænset mængde tilstande, f.eks. netværksresultater, brugerfladetilstande eller navigationshændelser.

Syntaks for forseglede klasser

Deklarer underklasser direkte i den samme klasse eller i den samme fil:

sealed class NetworkResult<out T> {
    data class Success<T>(val data: T) : NetworkResult<T>()
    data class Error(val message: String, val code: Int = 0) : NetworkResult<Nothing>()
    object Loading : NetworkResult<Nothing>()
}

fun handle(result: NetworkResult<String>) {
    when (result) {
        is NetworkResult.Success -> println("Data: ${result.data}")
        is NetworkResult.Error  -> println("Error ${result.code}: ${result.message}")
        NetworkResult.Loading   -> println("Loading...")
    }
}

Forseglet klasse + when (udtømmende)

Det stærke ved forseglede klasser er, at when er udtømmende. Compileren tvinger dig til at håndtere hver undertype — ingen glemte tilfælde:

sealed class UiState {
    object Loading : UiState()
    data class Success(val message: String) : UiState()
    data class Error(val error: String) : UiState()
}

fun render(state: UiState): String = when (state) {
    is UiState.Loading      -> "Showing spinner"
    is UiState.Success      -> "Show: ${state.message}"
    is UiState.Error        -> "Error: ${state.error}"
    // Compiler error if you remove any branch!
}

fun main() {
    println(render(UiState.Loading))
    println(render(UiState.Success("Loaded!")))
}

Forseglet klasse sammenlignet med enum

Begge repræsenterer en fast mængde værdier, men:

  • Enum — hver konstant er en enkelt instans uden ekstra data pr. variant
  • Forseglet klasse — hver variant kan indeholde forskellige data og være en klasse eller et objekt

Brug enum, når varianterne ikke har brug for data. Brug en forseglet klasse, når varianterne har brug for forskellige egenskaber.

Objektdeklarationer (singletoner)

object opretter en singleton — én instans, der oprettes efter behov og er trådsikker:

object AppConfig {
    const val BASE_URL = "https://api.example.com"
    const val TIMEOUT = 30L

    fun buildUrl(path: String) = "$BASE_URL/$path"
}

fun main() {
    println(AppConfig.BASE_URL)          // https://api.example.com
    println(AppConfig.buildUrl("users")) // https://api.example.com/users
}

Ledsagerobjekter

Et ledsagerobjekt ligger inde i en klasse og stiller medlemmer på klasseniveau til rådighed (ligesom Javas static). Det bruges ofte til fabrikationsmetoder:

class Token private constructor(val value: String) {
    companion object {
        fun create(raw: String): Token {
            val cleaned = raw.trim()
            require(cleaned.isNotEmpty()) { "Token must not be blank" }
            return Token(cleaned)
        }
    }
}

fun main() {
    val token = Token.create("  abc123  ")
    println(token.value)  // abc123
}

Dataklasser i en rigtig app

Kombiner dataklasser med forseglede klasser for at modellere tilstande på en overskuelig måde:

data class Post(val id: Int, val title: String, val body: String)

sealed class PostState {
    object Loading : PostState()
    data class Loaded(val posts: List<Post>) : PostState()
    data class Failed(val reason: String) : PostState()
}

fun showState(state: PostState) = when (state) {
    PostState.Loading        -> println("Fetching posts...")
    is PostState.Loaded      -> println("${state.posts.size} posts loaded")
    is PostState.Failed      -> println("Failed: ${state.reason}")
}

fun main() {
    showState(PostState.Loaded(listOf(
        Post(1, "Hello", "World"),
        Post(2, "Kotlin", "Rocks")
    )))
}

Hurtigt tjek

Hvilket udsagn beskriver bedst, hvad der adskiller forseglede klasser fra almindelige abstrakte klasser?

Opsummering: data- og forseglede klasser

Du har nu to effektive Kotlin-værktøjer:

  • data class — værdibaseret lighed, copy(), destrukturering og automatisk genereret toString()
  • sealed class — begrænset typehierarki, udtømmende when, og hver variant kan indeholde sine egne data
  • object — singletoner og ledsagerobjekter til fabrikationsmetoder

Tilsammen erstatter disse mønstre Javas standardkode og gør det muligt at modellere tilstande på en enkel og sikker måde.

Gratis at komme i gang

Lær Kotlin med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
36
Lektioner
152

Ofte stillede spørgsmål

Er lektionen “Data classes og sealed classes” gratis?

Ja — alle 3 lektioner i læringssporet Android Academy, inklusive “Data classes og sealed classes”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Android Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Data classes og sealed classes”?

Brug data classes til værdibaseret lighed og copy(), og sealed classes til komplette typehierarkier og tydelig modellering af tilstande. Du øver dig i Android Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Android Academy?

Der kræves ingen tidligere erfaring. Android Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Data classes og sealed classes”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Android Academy-lektion?

Ja. Alle Android Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Null-sikkerhed
  2. Klasser og objekter
  3. Data classes og sealed classes
  4. Extension functions og higher-order functions
← Tilbage til Android Academy