Kotlin Sealed Classes (密封類別)
Sealed Class (密封類別) 是一種特殊的類別,用來表示 受限的繼承結構 (Restricted Class Hierarchies)。 簡而言之,它就像是 超級強大的 Enum。
為什麼需要 Sealed Class?
Enum 雖然好用,但有個限制:每個 Enum 常數都只能是單例 (Singleton),無法攜帶自定義的狀態。 Sealed Class 允許每個子類別擁有自己的屬性、狀態,甚至是多個實例。
定義 Sealed Class
最常見的應用場景是用來定義 UI 狀態 (UI State)。
sealed class UiState {
// 單例狀態:載入中 (不需要帶資料)
object Loading : UiState()
// 成功狀態:攜帶資料 List<String>
data class Success(val data: List<String>) : UiState()
// 錯誤狀態:攜帶錯誤訊息 Exception
data class Error(val exception: Exception) : UiState()
}
搭配 when 使用
因為 Sealed Class 的子類別是 有限的 (Known at compile time),所以編譯器知道所有的可能性。
當你在 when 表達式中使用時,不需要寫 else 分支 (前提是你覆蓋了所有情況)。這讓程式碼更安全,因為如果你新增了一個狀態但忘了處理,編譯器會報錯。
fun handleState(state: UiState) {
when (state) {
is UiState.Loading -> {
println("Loading...")
}
is UiState.Success -> {
println("Got data: ${state.data}")
}
is UiState.Error -> {
println("Error: ${state.exception.message}")
}
// 不需要 else!
}
}
Sealed Interface
從 Kotlin 1.5 開始,你也使用 sealed interface。
如果你不需要繼承任何實作邏輯,只想要定義型別階層,sealed interface 會比 sealed class 更輕量且更有彈性 (因為類別只能單一繼承,但介面可以多重實作)。
sealed interface Result
data class Success(val value: Int) : Result
data class Failure(val error: String) : Result
總結:Enum vs Sealed Class
- Enum: 狀態是固定的常數,不能帶動態資料 (例如
Color.RED,Direction.NORTH)。 - Sealed Class: 狀態是有限的類別集合,每個狀態可以攜帶不同的資料實例 (例如
Success(data),Error(msg))。