Kotlin 列挙型クラス(Enum Classes)
列挙型クラス(enum class)
列挙型クラスは、classキーワードの前にenumを付けて宣言する。
各列挙型定数はオブジェクトであり、列挙型定数はカンマで区切られる。
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
fun main() {
println(Direction.NORTH)
}
Output:
NORTH
それぞれのEnumはEnum classのインスタンスなので、特定の値で初期化できる。
enum class Color(val strRgb: String, val hexaRgb: Int) {
RED("#f00", 0xFF0000),
GREEN("#0f0", 0x00FF00),
BLUE("#00f",0x0000FF ),
}
fun main() {
println(Color.RED)
println(Color.RED.name)
println(Color.RED.strRgb)
println(Color.RED.hexaRgb.toString(16))
}
Output:
RED
RED
#f00
ff0000
enum定義形式
enumキーワードを使用して列挙体を定義できる。- 定義された列挙体の最初の定数値は0から設定され、次は直前の定数値より1だけ増加して設定される。
- 不規則な値を定数値として設定したい場合は、定数名の横に括弧(
())を追加し、その中に目的の整数定数値を明示できる。 - 列挙体名の右側に
valで変数を宣言すると、その列挙型要素の定数値を確認できる。型指定によってordinal型を指定できる。
enumを使用する理由
- インスタンス生成と継承を防ぎ、定数値の型安全性を保証する。
- 列挙型クラスの最も基本的な使用理由は、型安全な列挙型(type-safe enums)を実装することである。
- コードが単純になり、可読性が高まる。
匿名クラス(Anonymous Classes)
Enum constantは、自身のanonymous classとmethodを宣言でき、base methodをoverrideできる。
enum class ProtocolState {
WAITING {
override fun signal() = TALKING
},
TALKING {
override fun signal() = WAITING
};
abstract fun signal(): ProtocolState
}
fun main() {
println(ProtocolState.TALKING.signal())
println(ProtocolState.WAITING.signal())
}
Output:
WAITING
TALKING
Enum classにメンバーを定義するときは、メンバー定義とenum constant定義をセミコロン(;)で区切る必要がある。
Enumの項目(entry)はネストされたクラスを持てない。
列挙型でのインターフェース実装(Implementing Interfaces in Enum Classes)
enum classは継承の代わりにinterfaceを使用する。
interfaceは、すべての項目のための1つのインターフェースメンバーを持つことも、anonymous class内にある各項目のためのインターフェースを持つこともできる。
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 t = 2
val u = 3
println("PLUS($t, $u) = ${IntArithmetics.PLUS.apply(t, u)}");
println("TIMES($t, $u) = ${IntArithmetics.TIMES.apply(t, u)}");
}
Output:
PLUS(2, 3) = 5
TIMES(2, 3) = 6
列挙型定数の操作(Working with enum constants)
Enum classは、定義されたenum constantのリストを取得でき、列挙型名でenum constantを取得できるsynthetic methodsを持つ。
これらのmethodsのsignatureは次のとおりである。
| メソッド | 説明 |
|---|---|
EnumClass.valueOf(value: String): EnumClass |
引数として渡された文字列と一致する、その列挙体の定数を返す。 |
EnumClass.values(): Array<EnumClass> |
その列挙体のすべての定数を保存した配列を生成して返す。 |
次の例では、列挙型クラスの一覧と特定の列挙型データを取得している。
fun main() {
println(Color.valueOf("RED").name)
println(Color.values().joinToString())
}
Output:
RED
RED, GREEN, BLUE
valueOf()メソッドは、一致するEnum constantがない場合にIllegalArgumentExceptionを発生させる。
enumValues<T>()、enumValueOf<T>()関数を通じて、generic方式でenum classのconstantにアクセスできる。
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
print(enumValues<T>().joinToString { it.name })
}
fun main() {
printAllValues<RGB>() // prints RED, GREEN, BLUE
}
Output:
RED, GREEN, BLUE
すべてのenum constantは、enum定義内での自身の名前(.name)と位置(.ordinal)を取得できるpropertyを持つ。
| メソッド | 説明 |
|---|---|
val name: String |
列挙型の名前を返す。 |
val ordinal: Int |
列挙型のインデックスを返す。 |
次の例では、名前と位置を取得している。
fun main() {
println(Color.RED.name)
println(Color.RED.ordinal)
}
Output:
RED
0