iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
Software Development

成為一名 Kotlin 後端攻城獅系列 第 23

Day 23 Sealed class, value class 和 Enum class

  • 分享至 

  • xImage
  •  

今天要來收尾了,類別這個主題講了8天了,我們即將以 sealed class, value class , enum class 收尾,沒有意外會主力著重在 sealed class,這種類型的類別將影響後面在 Kotlin 上撰寫 Functional Programming 的設計。話不多說,我們開始吧!

密封 (Sealed)

密封是什麼?跟我們生活中遇到的密封很像,他在封起來後就與外界隔絕了。這時候你會很好奇,哪個類別不是 code 寫完就定型了,為什麼需要這個呢?那我們從介紹它開始一層層揭開面紗。

從下面範例我們可以看出 sealed class 跟一般 class 相當不同:

sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

fun handleResult(result: Result) {
    when (result) {
        is Result.Success -> println("成功:${result.data}")
        is Result.Error -> println("錯誤:${result.message}")
        Result.Loading -> println("載入中...")
    }
}

上面範例可以看出 sealed class 本身是用來規範哪一些類別或是物件可以屬於這個 sealed class ,所以當我們制定一個端口 (API) 給外部服務來使用並指定一個 sealed class 作為回傳型別就會間接限定使用這個端口的工程師必須使用我制定下的這些類別。

另外,如果大家有注意到 handleResult 裡面的 when 判斷式 (控制流程) 就可以發現他不需要另外給一個 else 敘述做為預設值,這是因為當我們調用 Result 類別的物件作為判斷條件,它就只會有固定的選擇,這種觀念是 Functional Programming 裡面會提到的 “exhaustive” (窮舉/列舉)。 在狀態或情境可以事前知道有限的情況下使用這種寫法可以最大化避免使用 else 需要考慮到的各種錯誤情境,簡化處理錯誤或是預設值的成

當然除了類別之外我們也可以把這項設計套用在介面 (interface) 上,道理同放在類別上可以限制介面的種類可以讓實作以及調用。

Value class

相似於昨天介紹的 data class ,他們都是用來協助儲存資料用的類別,但不同於 data class 的是:

  1. 變數只能是 val
  2. 不具備 data class 所擁有的內建擴中函式, equals()hashCode()toString()copy()
  3. data class 能儲存多筆資料不同,value class 只能儲存一個。

讓我們直接看一個範例:

@JvmInline
value class Name(val value: String)

fun main() {
    // 創建一個 Name
    val name1 = Name("Alice")
    println(name1) // 輸出: Name(name=Alice)
    val name2 = Name("Alice")

    println(name1 == name2)  // 輸出: true
//  println(name1 === name2) // 輸出: Identity equality for arguments of types Person and Person is forbidden
// 	name1.value = "John"		   // 輸出: Val cannot be reassigned

    val name = name1.value
    println("姓名:$name") // 輸出: 姓名:Alice
}

範例中我們可以特別注意下面被註解的兩行, value class 並不提供我們對物件相同直接做檢查,因為本生就只能用 val 定義,所以所有的物件都是不同也不可修改的。熟悉 Kotlin 的讀者這時候會說:這跟 type aliases 有什麼不一樣嗎?結論是它的慨念確實相似,但在型別安全檢查上有些許差異,礙於篇幅我這邊直接送上官方說明,有興趣的讀者可以去啃一下XD Value class v.s. Type aliases (Kotlin Official)

Enum class

跟大多數程式語言的 enum 相同,Kotlin 裡的 enum class 是一個用來定義常數名稱集合的類別。這些常數在 enum class 中被列舉出來,並且可以像類別一樣被使用。這種結構提升易讀性與維護性。

以下是一個簡單的Kotlin enum class 範例:


// 定義一個名為Color的enum class 
enum class Color { RED, GREEN, BLUE, YELLOW, ORANGE } 

fun main() { 
		// 使用enum class的常數 
		val selectedColor: Color = Color.RED 
		// 檢查選擇的顏色並執行相應的動作 
		when (selectedColor) { 
				Color.RED -> println("選擇了紅色") 
				Color.GREEN -> println("選擇了綠色") 
				Color.BLUE -> println("選擇了藍色") 
				Color.YELLOW -> println("選擇了黃色") 
				Color.ORANGE -> println("選擇了橙色") 
		} 
}

在這個例子中,我們定義了一個 Colorenum class,其中包含了幾種不同的顏色。然後透過建立了一個 selectedColor 變數,並使用when 判斷式來窮舉出所有的顏色並印出相應的訊息。enum class 常被用於表示固定集合的常數。


上一篇
Day 22 Kotlin Data Class
下一篇
Day 24 Kotlin 擴充函式原理推測
系列文
成為一名 Kotlin 後端攻城獅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言