ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# [枚举类](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin--enum-index.html) ~~~ abstract class Enum<E : Enum<E>> : Comparable<E> ~~~ [TOC] **枚举类的最基本的用法是实现类型安全的枚举**: * 枚举常量:即枚举类下的对象,每个枚举类包含0个到多个枚举常量。`enum`关键字在类头中的`class`关键字前面。 ```kotlin enum class Direction { NORTH, SOUTH, WEST, EAST } ``` * **每个枚举常量都是一个对象,且枚举常量之间用逗号分隔。** * **不需要实例化枚举类就可以访问枚举常量** * 使用方式:`枚举类名.枚举常量.属性` ``` // 使用中缀符号访问枚举常量 Direction.NORTH.name Direction.SOUTH.name Direction.WEST.name Direction.EAST.name ``` ## 初始化 **因为每一个枚举都是枚举类的实例**,所以他们可以是这样初始化过的: ```kotlin enum class Color(val rgb: Int) { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) } ``` ## 匿名类 枚举常量还可以声明其带有相应方法以及覆盖了其基类方法的匿名类。(注意**是匿名类,而不是匿名内部类**) * 就是**枚举类的常量可以同时看成是一个同名匿名类** * 枚举常量支持枚举类,支持重载父类的方法,枚举常量匿名类规则和常量一致,但常量匿名类和父类的其它分量要用";"隔开 * **要实现枚举常量的匿名类**,则必须提供一个抽象方法(必须重写的方法)。且该方法定义在枚举类内部。而且必须在枚举常量的后面。 * 枚举变量之间使用逗号(`,`)分割开。但是最后一个枚举常量必须使用分号结束。不然定义不了抽象方法。 ```kotlin enum class ProtocolState { //枚举常量WAITING可看做一个同名匿名类 WAITING { override fun signal() = TALKING }, //枚举常量TALKING可看做一个同名匿名类 TALKING { override fun signal() = WAITING }; abstract fun signal(): ProtocolState } ``` 测试 ~~~ fun main(args: Array<String>) { val ev: ProtocolState = ProtocolState.WAITING println(ev.signal()) } ~~~ 运行结果 ``` TALKING ``` 如果枚举类定义任何成员,那么使用分号将成员定义中的枚举常量定义分隔开。 枚举条目不能包含内部类以外的嵌套类型(已在 Kotlin 1.2 中弃用)。 示例: ``` fun main(args: Array<String>) { ConsoleColor.BLACK.print() } enum class ConsoleColor(var argb : Int){ RED(0xFF0000){ override fun print() { println("我是枚举常量 RED ") } }, WHITE(0xFFFFFF){ override fun print() { println("我是枚举常量 WHITE ") } }, BLACK(0x000000){ override fun print() { println("我是枚举常量 BLACK ") } }, GREEN(0x00FF00){ override fun print() { println("我是枚举常量 GREEN ") } }; abstract fun print() } ``` 运行结果 ``` 我是枚举常量 BLACK ``` ## 在枚举类中实现接口 **一个枚举类可以实现接口但不能从类继承(实现接口,继承类都是用冒号表示)**,可以为所有条目提供统一的接口成员实现,也可以在相应匿名类中为每个条目提供各自的实现。只需将接口添加到枚举类声明中即可,如下所示: ```kotlin import java.util.function.BinaryOperator import java.util.function.IntBinaryOperator //sampleStart 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) } //sampleEnd fun main() { val a = 13 val b = 31 for (f in IntArithmetics.values()) { println("$f($a, $b) = ${f.apply(a, b)}") } } ``` ## 使用枚举常量 **示例** ~~~ enum class Color(var argb: Int) { RED(0xFF0000), WHITE(0xFFFFFF), BLACK(0x000000), GREEN(0x00FF00) } fun main(args: Array<String>) { //访问枚举变量属性 println("使用枚举常量") println("--------访问枚举变量属性--------") println("name = " + Color.RED.name + "\tordinal = " + Color.RED.ordinal) println("name = " + Color.WHITE.name + "\tordinal = " + Color.WHITE.ordinal) println("name = " + Color.BLACK.name + "\tordinal = " + Color.BLACK.ordinal) println("name = " + Color.GREEN.name + "\tordinal = " + Color.GREEN.ordinal) //使用valueOf()和values()检测 println("--------使用valueOf()和values()检测--------") println(Color.valueOf("RED")) println(Color.values()[0]) println(Color.values()[1]) println(Color.values()[2]) println(Color.values()[3]) //使用enumValues<T>()和 enumValueOf<T>()访问 println("--------使用enumValues<T>()和 enumValueOf<T>()访问--------") println(enumValues<Color>().joinToString { it.name }) println(enumValueOf<Color>("RED")) } ~~~ 运行结果 ``` 使用枚举常量 --------访问枚举变量属性-------- name = RED ordinal = 0 name = WHITE ordinal = 1 name = BLACK ordinal = 2 name = GREEN ordinal = 3 --------使用valueOf()和values()检测-------- RED RED WHITE BLACK GREEN --------使用enumValues<T>()和 enumValueOf<T>()访问-------- RED, WHITE, BLACK, GREEN RED ``` Kotlin 中的枚举类也有合成方法允许列出定义的枚举常量以及通过名称获取枚举常量。这些方法的签名如下(假设枚举类的名称是 `EnumClass`): ```kotlin EnumClass.valueOf(value: String): EnumClass EnumClass.values(): Array<EnumClass> ``` 如果指定的名称与类中定义的任何枚举常量均不匹配,`valueOf()` 方法将抛出 `IllegalArgumentException` 异常。 如:我们在上面示例中,`println(Color.valueOf("RED"))`下面添加`println(Color.valueOf("BLUE"))`运行IDE,控制台就会报错如下: ![](https://img.kancloud.cn/d6/6b/d66b4e5ae40a01f2349a9b2e0102f607_1100x205.png) 自 Kotlin 1.1 起,可以使用 `enumValues<T>()` 与 `enumValueOf<T>()` 函数以泛型的方式访问枚举类中的常量: ```kotlin enum class RGB { RED, GREEN, BLUE } inline fun <reified T : Enum<T>> printAllValues() { print(enumValues<T>().joinToString { it.name }) } printAllValues<RGB>() // 输出 RED, GREEN, BLUE ``` 每个枚举常量都具有在枚举类声明中获取其名称与位置的属性: ```kotlin val name: String val ordinal: Int ``` 枚举常量还实现了 [Comparable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-comparable/index.html) 接口,其中自然顺序是它们在枚举类中定义的顺序。