Sealed vs Enum vs Abstract

Which One?

enum classsealed class / interfaceabstract class / open
Set of subtypesfixed constantsfixed subclassesopen to anyone
Instances per caseexactly onemany (or one with object)many
Different data per caseno (same properties)yesyes
Exhaustive whenyesyesno (needs else)
ExampleDirection, Plan, OrderStatusUiState, Result, NetworkErrorBaseActivity, Account

Same Idea, Two Ways

Example

Use an enum when cases carry no extra data; switch to sealed types when they do.

enum class ConnectionType { WIFI, MOBILE, NONE }

sealed interface Connection {
    data class Wifi(val ssid: String) : Connection
    data class Mobile(val network: String, val signalBars: Int) : Connection
    data object Offline : Connection
}

fun describe(c: Connection) = when (c) {
    is Connection.Wifi -> "Wi-Fi: ${c.ssid}"
    is Connection.Mobile -> "${c.network} with ${c.signalBars} bars"
    Connection.Offline -> "No internet"
}

fun main() {
    println(ConnectionType.entries)
    listOf(Connection.Wifi("Home_5G"), Connection.Mobile("Jio 5G", 3), Connection.Offline)
        .forEach { println(describe(it)) }
}

Output

[WIFI, MOBILE, NONE]
Wi-Fi: Home_5G
Jio 5G with 3 bars
No internet