Kotlin 枚举类

204 阅读3分钟

在 Kotlin 中,‌枚举类(Enum Class) ‌ 用于定义一组有限的命名常量,支持附加属性、方法及自定义行为。以下是其核心特性、用法及示例:


一、枚举类的基本定义

1. 基础语法

enum class Direction {
    NORTH, SOUTH, EAST, WEST  // 枚举常量
}

// 使用示例
val currentDirection = Direction.NORTH
println(currentDirection) // 输出: NORTH

2. 带属性的枚举类

每个枚举常量可携带额外属性(需定义构造函数):

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

// 访问属性
println(Color.RED.rgb) // 输出: 16711680(即 0xFF0000 的十进制值)

二、枚举类的高级用法

1. 实现接口

枚举类可实现接口,为不同常量定义不同行为:

interface Action {
    fun execute()
}

enum class Operation : Action {
    ADD {
        override fun execute() = println("执行加法")
    },
    SUBTRACT {
        override fun execute() = println("执行减法")
    }
}

// 调用
Operation.ADD.execute() // 输出: 执行加法

2. 匿名类与自定义方法

每个枚举常量可通过匿名类覆盖方法或添加新逻辑:

enum class Planet(val mass: Double) {
    EARTH(5.97e24) {
        override fun description() = "人类的家园"
    },
    MARS(6.39e23) {
        override fun description() = "未来的殖民地"
    };

    abstract fun description()  // 抽象方法
}

// 使用
println(Planet.EARTH.description()) // 输出: 人类的家园

三、枚举类的常用方法

1. 遍历枚举常量

通过 values()enumValues<T>() 获取所有枚举实例:

enum class Weekday { MON, TUE, WED, THU, FRI }

// 遍历
Weekday.values().forEach { println(it) } 
// 输出: MON, TUE, WED, THU, FRI

2. 从字符串解析枚举

使用 valueOf() 或安全方法 enumValueOfOrNull(Kotlin 1.9+):

val day = Weekday.valueOf("MON") // 严格匹配,不区分大小写
val safeDay = enumValueOfOrNull<Weekday>("monday") // 返回 null

四、when 表达式与枚举类

利用 when 的穷尽性检查,确保处理所有枚举分支:

fun getWeather(direction: Direction) = when (direction) {
    Direction.NORTH -> "寒冷"
    Direction.SOUTH -> "炎热"
    Direction.EAST, Direction.WEST -> "多风"
}

println(getWeather(Direction.EAST)) // 输出: 多风

五、注意事项

  1. 性能与内存
    枚举类比普通常量占用更多内存(每个实例为对象),在性能敏感场景(如 Android)需谨慎使用。
  2. 单例特性
    每个枚举常量在 JVM 中是单例,线程安全且序列化友好。
  3. 构造函数限制
    枚举类的主构造函数只能是 private(默认隐式),不可在类外实例化。

六、实际应用场景

1. 状态管理

enum class DownloadStatus {
    IDLE, RUNNING, COMPLETED, FAILED
}

fun handleStatus(status: DownloadStatus) {
    when (status) {
        DownloadStatus.COMPLETED -> println("下载完成")
        DownloadStatus.FAILED -> println("下载失败")
        else -> println("状态未处理")
    }
}

2. 类型安全的配置

enum class HttpMethod {
    GET, POST, PUT, DELETE
}

fun sendRequest(method: HttpMethod, url: String) {
    // 根据 method 发送对应 HTTP 请求
}

七、与密封类(Sealed Class)的对比

特性枚举类(Enum Class)密封类(Sealed Class)
实例数量固定数量的常量(编译时确定)子类数量固定,但每个子类可携带不同数据
数据携带能力只能通过构造函数传递固定属性每个子类可定义独立属性及结构
适用场景简单常量集合(如状态、类型)复杂多态数据(如网络请求结果、UI 状态)

总结

  • 优先使用枚举类‌:当需要一组固定常量且需附加属性或方法时。
  • 替代方案考虑‌:若需更灵活的数据结构,使用密封类或普通类。
  • 注意性能影响‌:在资源受限环境中评估枚举类的使用必要性。