2023-12-08|閱讀時間 ‧ 約 5 分鐘

【Kotlin 入門指南】密封類別(sealed class)

【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 類型,像是 State1State2State3,它們不需要任何參數,代表這些狀態的存在即可。

密封類的成員也可以是帶有參數的類型,像是 State4,它是一個含有整數參數 value 的類型。這些帶參數的類型可以是一般的 class 或是 data class 類型。

接下來,在 MyClass 這個類別中,有一個接收 MySealedClass 作為參數的函式 show()。這個函式利用 when 表達式對傳入的 MySealedClass 密封類型進行模式匹配。根據不同的狀態,返回相對應的字串表示狀態。

需要特別注意的是,若沒有涵蓋到所有的密封類型,即缺少了對某個狀態的判斷,Kotlin 將會提示錯誤。為了避免這種情況,你可以加上 else 分支來處理未知的狀態,像是 else -> "未知狀態",這樣能確保所有情況都被考慮到。

最後,在 main() 函式中,展示了如何創建 MyClass 的實例並呼叫 show() 函式,透過不同的 MySealedClass 狀態輸出對應的結果。

這種模式匹配的方式能讓程式碼更為清晰,並且在處理有限類型集合時提供了更好的可擴展性和安全性。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.