Reading — step 1 of 6
Learn
sealed class restricts inheritance to a fixed set of subclasses, all in the same file. Combined with when, this gives you exhaustive pattern matching.
sealed class Result<out T> {
data class Ok<T>(val value: T) : Result<T>()
data class Err(val message: String) : Result<Nothing>()
}
fun describe(r: Result<Int>): String = when (r) {
is Result.Ok -> "got ${r.value}"
is Result.Err -> "failed: ${r.message}"
// no else needed — compiler knows all cases
}
The compiler forces exhaustiveness when when is used as an expression on a sealed type. Add a new variant → every when lights up at compile time.
Smart casts kick in inside is checks — r.value works without explicit cast because the compiler knows r is Ok in that branch.
Nothing is the bottom type — no instances. Result<Nothing> can be assigned to any Result<T> because Nothing is a subtype of everything. That's why Err doesn't need a type parameter.
Sealed interfaces (Kotlin 1.5+) work the same way — useful when you need multiple inheritance.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…