列舉類別
列舉類別最基本的用法是實作型別安全的列舉:
enum class Direction {
NORTH, SOUTH, WEST, EAST
}每個列舉常數都是一個物件。列舉常數之間以逗號分隔。
由於每個列舉都是列舉類別的執行個體,因此可以按照以下方式進行初始化:
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}匿名類別
列舉常數可以宣告自己的匿名類別及其對應的方法,也可以覆寫基底方法。
enum class ProtocolState {
WAITING {
override fun signal() = TALKING
},
TALKING {
override fun signal() = WAITING
};
abstract fun signal(): ProtocolState
}如果列舉類別定義了任何成員,請使用分號將常數定義與成員定義隔開。
在列舉類別中實作介面
列舉類別可以實作介面(但不能繼承類別),並為所有項目提供介面成員的通用實作,或者在匿名類別中為每個項目提供單獨的實作。這可以透過在列舉類別宣告中加入要實作的介面來完成,如下所示:
import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
PLUS {
override fun apply(t: Int, u: Int): Int = t + u
},
TIMES {
override fun apply(t: Int, u: Int): Int = t * u
};
override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}
fun main() {
val a = 13
val b = 31
for (f in IntArithmetics.entries) {
println("$f($a, $b) = ${f.apply(a, b)}")
}
}所有列舉類別預設都實作了 Comparable 介面。列舉類別中的常數是依自然順序定義的。若要了解更多資訊,請參閱排序。
使用列舉常數
Kotlin 中的列舉類別具有合成屬性與方法,用於列出已定義的列舉常數,以及根據名稱取得列舉常數。這些方法的簽章如下(假設列舉類別的名稱為 EnumClass):
EnumClass.valueOf(value: String): EnumClass
EnumClass.entries: EnumEntries<EnumClass> // 特殊化的 List<EnumClass>以下是其運作方式的範例:
enum class RGB { RED, GREEN, BLUE }
fun main() {
for (color in RGB.entries) println(color.toString()) // 印出 RED, GREEN, BLUE
println("The first color is: ${RGB.valueOf("RED")}") // 印出 "The first color is: RED"
}如果指定的名稱與類別中定義的任何列舉常數都不相符,valueOf() 方法將拋出 IllegalArgumentException。
在 Kotlin 1.9.0 引入 entries 之前,會使用 values() 函式來檢索列舉常數陣列。
每個列舉常數還具有屬性:name 和 ordinal,用於在列舉類別宣告中獲取其名稱和位置(從 0 開始):
enum class RGB { RED, GREEN, BLUE }
fun main() {
println(RGB.RED.name) // 印出 RED
println(RGB.RED.ordinal) // 印出 0
}為了減少使用列舉項目時的重複作業,請嘗試上下文相關解析(目前為預覽版)。此特性允許在已知預期型別時省略列舉類別名稱,例如在
when運算式中或指派給型別化變數時。
你可以使用 enumValues<T>() 和 enumValueOf<T>() 函式,以泛型的方式存取列舉類別中的常數。在 Kotlin 2.0.0 中,引入了 enumEntries<T>() 函式來取代 enumValues<T>() 函式。enumEntries<T>() 函式會傳回指定列舉型別 T 的所有列舉項目清單。
雖然仍支援 enumValues<T>() 函式,但我們建議你改用 enumEntries<T>() 函式,因為它的效能影響較小。每次呼叫 enumValues<T>() 時都會建立一個新陣列,而每次呼叫 enumEntries<T>() 時都會傳回相同的清單,這要高效得多。
例如:
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
println(enumEntries<T>().joinToString { it.name })
}
printAllValues<RGB>()
// RED, GREEN, BLUE若要了解更多關於內嵌函式和具體化型別參數的資訊,請參閱內嵌函式。
