枚举类(enum class)

100 阅读4分钟

一、声明方式及枚举常量

  • 关键字:enum
  • 枚举常量:即枚举类下的对象,每个枚举类包含0个到多个枚举常量。

1.1、声明

enum关键字在类头中的class关键字前面

声明格式:

enum class 类名{
      ...
}

1.2、枚举常量

枚举类中的每一个枚举常量都是一个对象,并且他们之间用逗号分隔。

例:

/**
 * 例:关于一个网络请求结果的枚举类
 */
enum class State{
    /*
         NORMAL : 正常
         NO_DATA : 数据为空
         NO_INTERNET : 网络未连接
         ERROR : 错误
         OTHER : 其他
     */

    NORMAL,NO_DATA,NO_INTERNET,ERROR,OTHER
}

1.3、访问枚举常量

不需要实例化枚举类就可以访问枚举常量

使用方式为:

枚举类名.枚举常量.属性

通过上面例子来实例讲解:

// 使用中缀符号访问枚举常量
State.NORMAL.name
State.NO_DATA.name
State.NO_INTERNET.name
State.ERROR.name
State.OTHER.name

这里只是让大家明白怎样去访问一个枚举常量。没有讲解到枚举常量的使用。枚举常量的使用请大家耐心的看下去。在下面会详细介绍怎样去使用它。

二、枚举常量的初始化

因为每一个枚举都是枚举类的实例,所以他们可以是初始化过的。

例:

 enum class Color(var argb : Int){
     RED(0xFF0000),
     WHITE(0xFFFFFF),
     BLACK(0x000000),
     GREEN(0x00FF00)
}

三、枚举常量的匿名类

  • 要实现枚举常量的匿名类,则必须提供一个抽象方法(必须重写的方法)。且该方法定义在枚举类内部。而且必须在枚举变量的后面。
  • 枚举变量之间使用逗号(,)分割开。但是最后一个枚举变量必须使用分号结束。不然定义不了抽象方法。
  • 在上面已经说过,每一个枚举常量就是一个对象。

例:

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 

四、枚举类的使用

  • 每个枚举常量都包含两个属性:name(枚举常量名)和ordinal(枚举常量位置)
  • 提供了values()和valueOf()方法来检测指定的名称与枚举类中定义的任何枚举常量是否匹配。
  • 自 Kotlin 1.1起,可以使用 enumValues()和 enumValueOf()函数以泛型的方式访问枚举类中的常量。

4.1、访问枚举变量属性

例:

fun main(args: Array<String>) {
    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)
}

enum class Color(var argb : Int){
     RED(0xFF0000),
     WHITE(0xFFFFFF),
     BLACK(0x000000),
     GREEN(0x00FF00)
}  

输出结果为:

name = RED  ordinal = 0
name = WHITE    ordinal = 1
name = BLACK    ordinal = 2
name = GREEN    ordinal = 3

4.2、使用enumValues()和 enumValueOf()访问

例: 枚举类还是上面例子中的Color类

println(enumValues<Color>().joinToString { it.name })
println(enumValueOf<Color>("RED"))

输出结果为:

RED, WHITE, BLACK, GREEN
RED

4.3、使用valueOf()和values()检测

例:

println(Color.valueOf("RED"))
println(Color.values()[0])
println(Color.values()[1])
println(Color.values()[2])
println(Color.values()[3])

输出结果为:

RED
RED
WHITE
BLACK
GREEN

其中,若使用Color.valueOf("不存在的枚举常量"),则会抛出IllegalArgumentException 异常,即枚举变量不存在。若使用Color.values()[大于枚举常量位置],则会抛出下标越界异常。

五、枚举类的源码分析

  • Enum.kt这个源文件。

在这里我大致的说明一下这个源文件的方法、属性等。有兴趣的可以去看看这个源文件。其实里面也没几个方法。

5.1、默认实现了companion object {}

  • 这也是我们访问枚举常量无需实例化枚举类的原因。

5.2、仅提供了两个属性

  • 即我们上面用到的枚举常量名称(name)和枚举常量位置(ordinal) 贴上这两个属性的源码:
/**
 * Returns the name of this enum constant, exactly as declared in its enum declaration.
 */
public final val name: String

/**
 * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant
 * is assigned an ordinal of zero).
 */
public final val ordinal: Int

5.3、实现了Comparable接口

  • 这也是我们能获取枚举常量位置的原因。

这是Enum.kt源文件。让大家看看它实现了Comparable接口

public abstract class Enum<E : Enum<E>>(name: String, ordinal: Int): Comparable<E>{
      ...
}

再来看看Comparable.kt里面做了些什么。其实里面就提供了一个方法罢了...

public interface Comparable<in T> {
    /**
     * Compares this object with the specified object for order. Returns zero if this object is equal
     * to the specified [other] object, a negative number if it's less than [other], or a positive number
     * if it's greater than [other].
     */
    public operator fun compareTo(other: T): Int
}