【Kotlin 入門指南】系列文章目錄:https://bit.ly/3t8awwL
Kotlin 線上課程教學影片:https://bit.ly/3qJ5a5Q
當物件有限定狀態時,我們常使用「列舉列別(enum class)」。不過,它較適合用來判斷簡單的狀態,不容許變數傳遞。當需要傳遞變數運算時,我們會採用「密封類別(sealed class)」,它可視為 enum class 的進階版。
密封類允許我們建立一個有限的類別階層結構。這些類別必須被定義在同一個檔案中,這樣做是為了確保封閉性。密封類別的主要特性在於其所有的子類別必須在同一個檔案中定義,這樣做有助於更有效地控制類別繼承結構。
要定義一個密封類別,我們需要使用 sealed
關鍵字來修飾類別聲明,然後在該類別內部定義其允許的子類別。這些子類別必須直接繼承自密封類別,並且可以在同一個檔案內或相同的封閉作用域中。
sealed class MySealedClass {
//密封類的成員,必須繼承自己類別 MySealedClass()
//如果沒有參數應為 object 類型
object State1 : MySealedClass()
object State2 : MySealedClass()
object State3 : MySealedClass()
//有參數可為 class 或 data class 類型
class State4(val value: Int) : MySealedClass()
}
class MyClass(private val data: MySealedClass) {
fun show() =
when (data) {
is MySealedClass.State1 -> "State1"
is MySealedClass.State2 -> "State2"
is MySealedClass.State3 -> "State3"
is MySealedClass.State4 -> "State4: ${data.value}"
//若少實現一種 MySealedClass 狀態條件判斷會噴錯,除非加入 else 判斷。
// else -> "未知狀態"
}
}
fun main() {
println(MyClass(MySealedClass.State1).show())
println(MyClass(MySealedClass.State4(100)).show())
}
在這個範例中,我們定義一個名為 MySealedClass
的密封類別,密封類的成員可以是 object 類型,像是 State1
、State2
和 State3
,它們不需要任何參數,代表這些狀態的存在即可。
密封類的成員也可以是帶有參數的類型,像是 State4
,它是一個含有整數參數 value
的類型。這些帶參數的類型可以是一般的 class 或是 data class 類型。
接下來,在 MyClass
這個類別中,有一個接收 MySealedClass
作為參數的函式 show()
。這個函式利用 when
表達式對傳入的 MySealedClass
密封類型進行模式匹配。根據不同的狀態,返回相對應的字串表示狀態。
需要特別注意的是,若沒有涵蓋到所有的密封類型,即缺少了對某個狀態的判斷,Kotlin 將會提示錯誤。為了避免這種情況,你可以加上 else
分支來處理未知的狀態,像是 else -> "未知狀態"
,這樣能確保所有情況都被考慮到。
最後,在 main()
函式中,展示了如何創建 MyClass
的實例並呼叫 show()
函式,透過不同的 MySealedClass
狀態輸出對應的結果。
這種模式匹配的方式能讓程式碼更為清晰,並且在處理有限類型集合時提供了更好的可擴展性和安全性。