【Kotlin】第10課-列舉(Enum)

對於同一個類別,絕大多數的物件都有自己的屬性組合,就像產品一樣,有各自的名稱、價格、材質等。而有些類別,它的物件就只有固定那幾個而已。例如網站的會員級別可分為銅、銀、金,大學的學院可分為商業、語文、電資、藝術等。

像這種只有固定物件的類別,可以採用「列舉」(enumeration)的概念來設計。在寫程式的期間就定義好各個物件,並直接利用。

一、建立列舉

我們設計一個簡單的列舉類別,下面的範例會列出貨幣種類,分別是美金、人民幣、日圓、澳幣與臺幣。

enum class CurrencyType {
USD, CNY, JPY, AUD, TWD
}

列舉也可以像一般的類別那樣,透過建構式宣告屬性。此處的屬性包含貨幣的中文名稱和對臺幣的匯率。

enum class CurrencyType(val chineseName: String,
val simpleExRate: Double) {
USD("美元", 30.0),
CNY("人民幣", 4.5),
JPY("日圓", 0.3),
AUD("澳幣", 20.0),
TWD("臺幣", 1.0)
}


二、使用列舉

列舉如同其他資料型態,也能作為類別的屬性。以下筆者設計一個存款帳戶的類別,以幣別作為其中一個屬性。

class CurrentAccount(val id: String,
val currencyType: CurrencyType,
var balance: Double) {
}

接著撰寫一段程式,建立數個 CurrentAccount 物件,再印出相關資訊。並將餘額透過匯率換算為臺幣。

val ac1 = CurrentAccount("1", CurrencyType.USD, 3027.5)
val ac2 = CurrentAccount("2", CurrencyType.CNY, 400.0)
val ac3 = CurrentAccount("3", CurrencyType.JPY, 1800.0)

val accounts = listOf(ac1, ac2, ac3)
for (ac in accounts) {
var info = ""

info += "幣別:${ac.currencyType.chineseName}\n"
info += "餘額:${ac.balance}\n"
info += "換算臺幣:${ac.balance * ac.currencyType.simpleExRate}\n"

println(info)
}


三、名稱與物件互轉

這些列舉的物件,都是由我們自行取名,例如前面範例的 USDJPY 等。Enum 類別提供了內建的屬性與方法,能取得列舉物件的名稱,或藉由名稱字串來取得對應的物件。

enum class CurrencyType(val chineseName: String,
val simpleExRate: Double) {
// 其餘省略
USD("美元", 30.0);

override fun toString() = "$chineseName ${super.toString()}"
}

fun main(args: Array<String>) {
// 取得名稱,印出:USD
println(CurrencyType.USD.name)

// 取得物件並比對,印出:true
println(CurrencyType.valueOf("USD") == CurrencyType.USD)

// 印出:美金 USD
println(CurrencyType.USD.toString())
}

name 屬性代表列舉物件的名稱。使用 valueOf 方法,可傳入字串,並取得名稱大小寫相符的物件。若物件不存在,會拋出例外。另外,toString 方法預設會回傳 name 屬性的值,讀者可以自行覆寫。在 Java 中,Enum 的 name 是方法而非屬性,且無法覆寫。


四、列舉物件的序數

列舉類別還內建另一個叫做 ordinal 的屬性,它代表的是該物件在類別中的順序,就像陣列與 List 的索引。以第一節的範例為例,USD 宣告在第一個,因此 ordinal 的值為0。依此類推,TWD 的值為4。

下面筆者提供一個利用序數來排序的範例。

val ac1 = CurrentAccount("1", CurrencyType.AUD, 100.0)
val ac2 = CurrentAccount("2", CurrencyType.USD, 200.0)
val ac3 = CurrentAccount("3", CurrencyType.JPY, 300.0)
val ac4 = CurrentAccount("4", CurrencyType.TWD, 400.0)
val ac5 = CurrentAccount("5", CurrencyType.CNY, 500.0)

val accounts = listOf<>(ac1, ac2, ac3, ac4, ac5)
.sortedBy { it.currencyType.ordinal }

for (ac in accounts) {
println(ac.currencyType.name)
}

建立一個 List,存放著不同幣別的存款帳戶。透過 sortedBy 方法,可以將元素依照指定的屬性來排序。上面 sortedBy 方法中的「it」,代表的是 CurrentAccount 元素本身。在這部份,排序的依據是幣別的序數,因此存款帳戶的順序都會排列成與幣別的宣告順序相同。


五、取得所有列舉物件

如果想要取得所有列舉出的物件,可以使用 values 方法,它會回傳一個包含全部列舉物件的陣列。

println("本程式支援的幣別如下:")

val types: Array<CurrencyType> = CurrencyType.values()
for (type in types) {
println(type.chineseName)
}

上一篇:【Kotlin】第9課-介面(Interface)

下一篇:【Kotlin】第11課-單例與伴生物件

留言