# Sealed Types and Enums — Kotlin

Source: https://www.skillbyai.com/en/kotlin/c-sealed

> Closed hierarchies with exhaustive when.

## Model every possible state

An `enum class` defines a fixed set of constants, which can have properties and methods; `entries` lists them (in recent versions, replacing `values()`). A **sealed class** or **sealed interface** restricts its direct subtypes to the same module and package, so the compiler knows every subtype. Subtypes can be `data class`es carrying different data, or `data object`s for singletons. Because the set is closed, a `when` over a sealed type is **exhaustive without `else`**, and adding a new subtype makes the compiler flag every `when` that must handle it. This is ideal for UI state, results and commands.

## Loading state with a sealed interface

Exhaustive when, no else branch.

```kotlin
sealed interface LoadState {
    data object Loading : LoadState
    data class Success(val items: List<String>) : LoadState
    data class Error(val message: String, val retryable: Boolean) : LoadState
}

enum class Priority(val weight: Int) { LOW(1), MEDIUM(5), HIGH(10) }

fun render(state: LoadState): String = when (state) {
    LoadState.Loading -> "Spinner"
    is LoadState.Success -> "Showing ${state.items.size} items"     // smart cast
    is LoadState.Error -> if (state.retryable) "Retry: ${state.message}" else state.message
}

fun maxWeight(): Int = Priority.entries.maxOf { it.weight }
```

## Avoid else on sealed when

Adding `else` to a `when` over a sealed type silences the compiler when a new subtype appears. Listing every case keeps the exhaustiveness check working for you.

**Quiz:** Why can `when` over a sealed interface omit `else`?

- [ ] when never needs else
- [ ] Sealed types cannot be used in when
- [x] The compiler knows all direct subtypes, so it can check exhaustiveness
- [ ] Sealed types are always enums

*Answer:* The compiler knows all direct subtypes, so it can check exhaustiveness. Sealed hierarchies are closed.
