Skip to content
Kotlin

Sealed Classes

Model closed hierarchies and UI state with sealed classes and when.

#sealed#when#adts

Code

kotlin
// Sealed interface for closed hierarchies
sealed interface Shape {
    fun area(): Double
}

data class Circle(val radius: Double) : Shape {
    override fun area() = Math.PI * radius * radius
}

data class Rectangle(val w: Double, val h: Double) : Shape {
    override fun area() = w * h
}

object Triangle : Shape {
    override fun area() = 0.0
}

fun describe(s: Shape): String = when (s) {
    is Circle -> "circle area=${s.area()}"
    is Rectangle -> "rect area=${s.area()}"
    Triangle -> "triangle placeholder"
    // no else needed - compiler knows all cases
}

fun main() {
    val shapes: List<Shape> = listOf(
        Circle(2.0),
        Rectangle(3.0, 4.0),
        Triangle,
    )
    shapes.forEach(::println)
    shapes.forEach { println(describe(it)) }
}

// Sealed class with nested state for UI events
sealed class UiState<out T> {
    object Loading : UiState<Nothing>()
    data class Success<T>(val data: T) : UiState<T>()
    data class Error(val message: String) : UiState<Nothing>()
}

fun render(state: UiState<String>) = when (state) {
    is UiState.Loading -> "spinner"
    is UiState.Success -> state.data
    is UiState.Error -> "error: ${state.message}"
}

println(render(UiState.Loading))
println(render(UiState.Success("hello")))
println(render(UiState.Error("oops")))