Kotlin Tutorial(14)列舉型態 by Michael | CodeData
top

Kotlin Tutorial(14)列舉型態

分享:
tags: kotlin enum

Kotlin Tutorial(13)多型的特性與應用 << 前情

設計應用程式的時候,除了基本的繼承架構外,通常也需要一些資料結構,例如產品分類、會員等級,或是項目的顏色。這類的應用通常是少數幾個固定的資料,使用變數或類別設計的話,會是比較麻煩的。接下來要討論Kotlin提供的列舉型態,它是一種特殊的類別,非常適合用來設計這類資料結構。

認識列舉類別

一個記事資料App,可以讓使用者依照自己的需求,設定每一個記事項目的顏色,例如把重要的項目設定為紅色,這樣的設計可以讓應用程式提供更清楚的記事資料畫面:

kt_14_01
kt_14_02

應用程式提供幾種可以設定的記事資料顏色,以上面的畫面來說有六種顏色,使用者為記事項目選擇顏色以後,應用程式就需要把顏色保存在記事資料。像這類資料結構可以在應用程式宣告像這樣的列舉類別:

package net.macdidi5.kotlin.tutorial.ch14

// 宣告顏色列舉型態,包含六個顏色成員
enum class Colors01 {
    // 列出所有成員的名稱,有六種顏色的名稱,每一個名稱之間使用逗號隔開
    LIGHTGREY, BLUE, PURPLE,
    GREEN, ORANGE, RED
}

上面宣告的列舉類別Colors01,是一個特殊的類別,宣告與用法都跟一般的類別不一樣。列舉類別型態的變數,只能指定在類別中宣告好的成員名稱:

// 宣告紅、藍、綠三個顏色變數
val c01: Colors01 = Colors01.RED
val c02: Colors01 = Colors01.BLUE
val c03: Colors01 = Colors01.GREEN

println("$c01, $c02, $c03")
// 顯示: RED, BLUE, GREEN

Kotlin會自動為列舉類別加入一些函式,例如把字串轉換為列舉類別型態,可以呼叫Kotlin自動加入的valueOf函式:

// 把紅、藍、綠顏色名稱字串轉換為列舉型態變數
val c04: Colors01 = Colors01.valueOf("RED")
val c05: Colors01 = Colors01.valueOf("BLUE")
val c06: Colors01 = Colors01.valueOf("GREEN")

println("$c04, $c05, $c06")
// 顯示: RED, BLUE, GREEN

Kotlin自動加入的函式還有values,它可以傳回所有宣告在這個列舉類別型態裡面的成員,型態是列舉類別陣列。每一個列舉類別成員有Kotlin自動加入的ordinal與name兩個屬性,分別是成員的索引編號(Int)和名稱(String):

// 取得包含列舉型態所有成員的陣列
val cs: Array<Colors01> = Colors01.values()

for (c in cs) {
    println("${c.ordinal}: ${c.name}")
}
// 顯示:
//    0: LIGHTGREY
//    1: BLUE
//    2: PURPLE
//    3: GREEN
//    4: ORANGE
//    5: RED

判斷列舉型態變數

宣告好顏色列舉類別以後,應用程式為了設定記事項目的顏色,需要另外宣告一個判斷顏色代碼的函式:

enum class Colors01 {
    LIGHTGREY, BLUE, PURPLE,
    GREEN, ORANGE, RED
}

// 傳回參數的顏色代碼
fun getColorCode(color: Colors01) =
        // 判斷顏色並傳回對應的代碼
        when (color) {
            Colors01.LIGHTGREY -> 0XD3D3D3
            Colors01.BLUE -> 0X33B5E5
            Colors01.PURPLE -> 0XAA66CC
            Colors01.GREEN -> 0X99CC00
            Colors01.ORANGE -> 0XFFBB33
            Colors01.RED -> 0XFF4444
        }

應用程式需要設定記事顏色的時候,可以呼叫上面的函式取得對應的顏色代碼:

val c01: Colors01 = Colors01.RED
val c02: Colors01 = Colors01.BLUE
val c03: Colors01 = Colors01.GREEN

// toString(16)可以把整數轉換為16進位字串
println("$c01: ${getColorCode(c01)}, ${getColorCode(c01).toString(16)}")
println("$c01: ${getColorCode(c02)}, ${getColorCode(c02).toString(16)}")
println("$c01: ${getColorCode(c03)}, ${getColorCode(c03).toString(16)}")
// 顯示:
//    RED: 16729156, ff4444
//    RED: 3388901, 33b5e5
//    RED: 10079232, 99cc00

為列舉類別成員加入對應的資料

如果應用程式需要的列舉類別,每一個成員都一個固定的對應資料,例如上面說明的顏色代碼。這類需求可以使用下面的語法,把對應的資料整合在列舉類別裡面:

enum class 名稱(val 參數名稱: 參數型態) {
    成員名稱(對應的值),...
}

下面的列舉類別額外加入接收顏色代碼參數的主要建構式,再把每一個顏色對應的代碼設定在成員後面:

package net.macdidi5.kotlin.tutorial.ch14

// 如果列舉型態需要包含每一個成員對應的資料,
//   在宣告的時候加入成員對應資料的參數
enum class Colors02(val value: Int) {
    // 在每一個成員名稱後的左右刮號裡面填入對應的資料
    LIGHTGREY(0XD3D3D3), BLUE(0X33B5E5), PURPLE(0XAA66CC),
    GREEN(0X99CC00), ORANGE(0XFFBB33), RED(0XFF4444)
}

整合成員對應資料的列舉類別,除了一般的使用方式外,可以直接使用主要建構式的參數名稱,取得每一個成員對應的資料:

val c01 = Colors02.RED
val c02 = Colors02.BLUE
val c03 = Colors02.GREEN

// 列舉型態變數多了建構式參數指定的屬性
println("$c01: ${c01.value}")
println("$c02: ${c02.value}")
println("$c03: ${c03.value}")
// 顯示:
//    RED: 16729156
//    BLUE: 3388901
//    GREEN: 10079232    

雖然為列舉類別加入主要建構式,不過它不可以跟一般類別一樣,呼叫建構式建立物件:

// 編譯錯誤,不可以呼叫建構式
// val c = Colors02(0XFF4444)

Kotlin自動加入的valueOf函式,可以把字串轉換為列舉類別型態。如果應用程式需要把成員對應的資料,轉換為列舉類別型態,就需要自己撰寫函式執行判斷與轉換的工作:

enum class Colors02(val value: Int) {
    LIGHTGREY(0XD3D3D3), BLUE(0X33B5E5), PURPLE(0XAA66CC),
    GREEN(0X99CC00), ORANGE(0XFFBB33), RED(0XFF4444);
}

// 接收顏色代碼參數,傳回對應的列舉型態變數
fun parseColor(value: Int): Colors02 {
    // 設定預設的顏色為LIGHTGREY
    var result: Colors02 = Colors02.LIGHTGREY

    for (c in Colors02.values()) {
        // 判斷顏色代碼
        if (value == c.value) {
            result = c
            break
        }
    }

    return result
}    

下面的程式片段示範轉換顏色代碼的作法:

// 呼叫函式把顏色代碼轉換為列舉型態變數
val c04 = parseColor(0XFF4444)
val c05 = parseColor(0X33B5E5)
val c06 = parseColor(0X000000)

println("\n$c04, $c05, $c06")
// 顯示: RED, BLUE, LIGHTGREY

宣告額外的函式

如果列舉型態變數需要執行一些額外的處理,例如把整數的顏色代碼轉換為十六進位,你可以把這類的函式整合在列舉類別裡面:

package net.macdidi5.kotlin.tutorial.ch14

enum class Colors03(val value: Int) {
    LIGHTGREY(0XD3D3D3), BLUE(0X33B5E5), PURPLE(0XAA66CC),
    GREEN(0X99CC00), ORANGE(0XFFBB33), RED(0XFF4444);

    // 為列舉型態加入函式,傳回顏色代碼十六進位的字串
    fun colorCode() = "0X${value.toString(16).toUpperCase()}"
}    

為列舉類別加入函式以後,就可以使用列舉型態變數呼叫這些函式:

val c01 = Colors03.RED
val c02 = Colors03.BLUE
val c03 = Colors03.GREEN

// 可以使用列舉型態變數呼叫函式
println("$c01: ${c01.colorCode()}")
println("$c02: ${c02.colorCode()}")
println("$c03: ${c03.colorCode()}")
// 顯示:
//    RED: 0XFF4444
//    BLUE: 0X33B5E5
//    GREEN: 0X99CC00   

使用列舉型態

設計好需要的顏色列舉類別後,就可以在記事類別中使用它來儲存顏色,而且可以使用整合的顏色代碼,在畫面顯示記事項目的顏色:

package net.macdidi5.kotlin.tutorial.ch14

// 為記事類別加入顏色屬性,預設值為Colors02.LIGHTGREY
class Item(val id: Long, var title: String, var content: String,
             var color: Colors02 = Colors02.LIGHTGREY) {

    fun getDetails() =
            "Item01(id=$id, title=$title, content=$content), color=${color}"
}

fun main(args: Array<String>) {
    val item01 = Item(1, "Hello", "World", Colors02.RED)
    println(item01.getDetails())
    // 顯示: Item(id=1, title=Hello, content=World), color=RED

    val item02 = Item(2, "Hi", "Kotlin", Colors02.BLUE)
    println("id: ${item02.id}, color.value: ${item02.color.value}")
    // 顯示: id: 2, color.value: 3388901

    val item03 = Item(3, "Greeting", "Good morning")
    println("id: ${item03.id}, color: ${item03.color}, color.value: ${item03.color.value}")
    // 顯示: iid: 3, color: LIGHTGREY, color.value: 13882323
}

下一步

API或Android的應用程式設計架構,經常使用的介面(Interface)是接下來討論的主題,包含設計與使用interface以後,為了讓程式碼比較清楚一些,也會使用巢狀類別與匿名類別的設計。

相關的檔案都可以在GitHub瀏覽與下載。

https://github.com/macdidi5/Kotlin-Tutorial

分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

熱門論壇文章

熱門技術文章