0Pricing
Kotlin Academy · Lektion

Sealed Hierarchies verschachteln und kombinieren

Erstellen Sie komplexe Zustandsautomaten durch das Verschachteln von Sealed Types.

Sealed Hierarchies verschachteln und kombinieren ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Zustandsbäume kombinieren

In der Praxis hat ein Zustand oft mehrere Dimensionen. Verschachteln Sie sealed-Typen oder kombinieren Sie separate Hierarchien, um komplexe Domänen übersichtlich zu modellieren.

Verschachtelte sealed class

Deklarieren Sie untergeordnete sealed-Typen innerhalb eines übergeordneten sealed-Typs. Der Compiler erzwingt weiterhin die Vollständigkeit über den gesamten Baum.

sealed class UiState {
    object Loading : UiState()
    sealed class Loaded : UiState() {
        data class Success(val items: List<String>) : Loaded()
        data class Empty(val message: String) : Loaded()
    }
    data class Error(val msg: String) : UiState()
}
fun render(s: UiState) = when (s) {
    UiState.Loading -> "loading"
    is UiState.Loaded.Success -> "${s.items.size} items"
    is UiState.Loaded.Empty -> "empty: ${s.message}"
    is UiState.Error -> "err: ${s.msg}"
}
fun main() {
    println(render(UiState.Loaded.Success(listOf("a", "b"))))
}

Sealed Interfaces für Mixins

Verwenden Sie sealed Interfaces, wenn ein Zustand mehrere voneinander unabhängige Aspekte besitzt — jeder Aspekt wird durch ein anderes Interface dargestellt.

sealed interface Authenticated
data class User(val id: Int) : Authenticated
object Guest
sealed interface Permission
object Read : Permission
object Write : Permission
fun describe(a: Authenticated, p: Permission): String = when {
    a is User && p is Write -> "user ${a.id} can write"
    a is User -> "user ${a.id} can read"
    else -> "?"
}
fun main() {
    println(describe(User(1), Write))
}

Hierarchien kombinieren

Übergeben Sie zwei sealed-Werte und verzweigen Sie anhand ihrer Kombination — verwenden Sie ein when mit Guards.

sealed class Theme { object Light : Theme(); object Dark : Theme() }
sealed class Lang { object En : Lang(); object Tr : Lang() }
fun greet(theme: Theme, lang: Lang) = when {
    theme is Theme.Dark && lang is Lang.Tr -> "Karanlik Merhaba"
    theme is Theme.Light && lang is Lang.Tr -> "Aydinlik Merhaba"
    theme is Theme.Dark -> "Dark Hello"
    theme is Theme.Light -> "Light Hello"
    else -> "?"
}
fun main() {
    println(greet(Theme.Dark, Lang.Tr))
}

Zustandsautomat mit verschachtelten Varianten

Modellieren Sie mehrstufige Abläufe als verschachtelte sealed-Typen — jeder Schritt hat seine eigenen Varianten.

sealed class Checkout {
    object Start : Checkout()
    sealed class Payment : Checkout() {
        object Pending : Payment()
        data class Failed(val reason: String) : Payment()
        object Captured : Payment()
    }
    object Shipped : Checkout()
    object Delivered : Checkout()
}
fun describe(c: Checkout) = when (c) {
    Checkout.Start -> "starting"
    Checkout.Payment.Pending -> "awaiting payment"
    is Checkout.Payment.Failed -> "payment failed: ${c.reason}"
    Checkout.Payment.Captured -> "paid"
    Checkout.Shipped -> "shipped"
    Checkout.Delivered -> "delivered"
}
fun main() {
    println(describe(Checkout.Payment.Failed("card declined")))
}

Sealed-Hierarchien modulübergreifend wiederverwenden

Sealed-Typen werden am besten pro Modul definiert. Für eine modulübergreifende Kombination stellen Sie ein sealed interface bereit, damit jedes Modul eigene Implementierungen hinzufügen kann.

sealed interface Notification
data class Email(val to: String) : Notification
data class Sms(val phone: String) : Notification
fun send(n: Notification) = when (n) {
    is Email -> "sending email to ${n.to}"
    is Sms -> "texting ${n.phone}"
}
fun main() {
    println(send(Email("a@example.com")))
}

Gemeinsame Basiseigenschaften

Sealed classes können gemeinsame Eigenschaften deklarieren — alle Subtypen erben diese. So bleiben Zustand und Metadaten DRY.

sealed class HttpResponse(val code: Int) {
    class Ok(val body: String) : HttpResponse(200)
    class NotFound(val path: String) : HttpResponse(404)
    class ServerError(val cause: String) : HttpResponse(500)
}
fun describe(r: HttpResponse) = "[${r.code}] " + when (r) {
    is HttpResponse.Ok -> r.body
    is HttpResponse.NotFound -> "not found: ${r.path}"
    is HttpResponse.ServerError -> "fail: ${r.cause}"
}
fun main() {
    println(describe(HttpResponse.Ok("hello")))
}

Rekursive Bäume modellieren

Sealed-Typen beschreiben rekursive Strukturen wie Ausdrucksbäume auf natürliche Weise.

sealed class Expr {
    data class Num(val value: Int) : Expr()
    data class Add(val left: Expr, val right: Expr) : Expr()
    data class Mul(val left: Expr, val right: Expr) : Expr()
}
fun eval(e: Expr): Int = when (e) {
    is Expr.Num -> e.value
    is Expr.Add -> eval(e.left) + eval(e.right)
    is Expr.Mul -> eval(e.left) * eval(e.right)
}
fun main() {
    val expr = Expr.Add(Expr.Num(3), Expr.Mul(Expr.Num(4), Expr.Num(5)))
    println(eval(expr)) // 23
}

Mit Generics kombinieren

Sealed-Typen können generisch sein und typisierte Ergebnis-Wrapper wie Result<T> ermöglichen.

sealed class ApiResult<out T> {
    data class Success<T>(val data: T) : ApiResult<T>()
    data class Failure(val message: String) : ApiResult<Nothing>()
}
fun handle(r: ApiResult<String>) = when (r) {
    is ApiResult.Success -> "got ${r.data}"
    is ApiResult.Failure -> "err: ${r.message}"
}
fun main() {
    println(handle(ApiResult.Success("hi")))
    println(handle(ApiResult.Failure("nope")))
}

Anti-Pattern: Zu tiefe Verschachtelung

Tiefe Verschachtelung verschleiert die Absicht. Wenn ein sealed-Baum mehr als zwei Ebenen tief ist, sollten Sie ihn abflachen oder Teilbäume in eigene Dateien auslagern.

sealed class Top {
    sealed class Mid : Top() {
        sealed class Deep : Mid() {
            object Leaf : Deep()
        }
    }
}
fun main() {
    val l = Top.Mid.Deep.Leaf
    println(l::class.simpleName)
}

Durch Komposition kombinieren

Wenn zwei Zustandsdimensionen unabhängig sind, bevorzugen Sie Komposition (eine data class, die zwei sealed-Werte umschließt) gegenüber tief verschachtelten Hierarchien.

sealed class Loading { object Active : Loading(); object Idle : Loading() }
sealed class Auth { data class Signed(val id: Int) : Auth(); object Anon : Auth() }
data class AppState(val loading: Loading, val auth: Auth)
fun main() {
    val s = AppState(Loading.Active, Auth.Signed(1))
    println(s)
}

Kurztest

Welcher Ansatz wird empfohlen, wenn zwei Zustandsdimensionen unabhängig sind?

Zusammenfassung

Verschachteln Sie sealed-Typen für baumförmige Zustände; kombinieren Sie unabhängige sealed-Hierarchien durch Komposition (eine umschließende data class). Fügen Sie einer sealed-Basisklasse gemeinsame Eigenschaften hinzu, verwenden Sie Generics für typisierte Ergebnisse und modellieren Sie rekursive Strukturen auf natürliche Weise. Halten Sie die Verschachtelung flach.

Häufig gestellte Fragen

Ist die Lektion „Sealed Hierarchies verschachteln und kombinieren“ kostenlos?

Ja — der vollständige Text von „Sealed Hierarchies verschachteln und kombinieren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Sealed Hierarchies verschachteln und kombinieren“?

Erstellen Sie komplexe Zustandsautomaten durch das Verschachteln von Sealed Types. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Sealed Hierarchies verschachteln und kombinieren“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. sealed class vs. sealed interface: Wann welche Variante verwendet wird
  2. Vollständige when-Ausdrücke mit Sealed Hierarchies
  3. UI-Zustände mit Sealed Classes modellieren
  4. Sealed Hierarchies verschachteln und kombinieren
← Zurück zu Kotlin Academy