對於同一個類別,絕大多數的物件都有自己的屬性組合,就像產品一樣,有各自的名稱、價格、材質等。而有些類別,它的物件就只有固定那幾個而已。例如網站的會員級別可分為銅、銀、金,大學的學院可分為商業、語文、電資、藝術等。
像這種只有固定物件的類別,可以採用「列舉」(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)
}
三、名稱與物件互轉
這些列舉的物件,都是由我們自行取名,例如前面範例的 USD、JPY 等。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)
}
留言
張貼留言