Kotlin Tutorial · Object-Oriented Kotlin · Lesson 16 of 31
Kotlin Enums and Sealed Classes
Model fixed sets of values with enum classes and closed hierarchies with sealed classes and exhaustive when.
enum class
Enums can have properties and functions. entries lists the values and valueOf parses a name.
enum class Plan(val monthlyPrice: Double) {
FREE(0.0), PRO(10.11), TEAM(25.0);
fun yearly() = monthlyPrice * 12
}
fun main() {
for (plan in Plan.entries) println("${plan.name} ${plan.ordinal} ${"%.2f".format(plan.yearly())}")
println(Plan.valueOf("PRO").monthlyPrice)
}
Output
FREE 0 0.00 PRO 1 121.32 TEAM 2 300.00 10.11
Run this on your computer — see “Get Started” for setup.
Sealed classes and interfaces
A sealed hierarchy has a fixed set of subtypes known at compile time, which can carry different data. A when
over a sealed type is exhaustive without else: add a subtype and the compiler shows every when you need to
update. This is the standard way to model results and UI state.
sealed interface LoadState {
data object Loading : LoadState
data class Success(val items: List<String>) : LoadState
data class Error(val message: String) : LoadState
}
fun render(state: LoadState): String = when (state) { // exhaustive: no else needed
LoadState.Loading -> "Spinner"
is LoadState.Success -> "List of ${state.items.size} items"
is LoadState.Error -> "Error: ${state.message}"
}
fun main() {
listOf(LoadState.Loading, LoadState.Success(listOf("a", "b")), LoadState.Error("offline"))
.forEach { println(render(it)) }
}
Output
Spinner List of 2 items Error: offline
Run this on your computer — see “Get Started” for setup.
Test yourself
Why doesn't a when over a sealed type need an else branch?
else is optional everywhereThe compiler knows every subtype, so it can check the when is exhaustiveSealed classes can't be used in whenIt returns null by default
Show answer
Answer: The compiler knows every subtype, so it can check the when is exhaustive