枚举类
本课属于 Coddy Kotlin 学习旅程的“面向对象编程”单元。第 33 课,共 57 课。
enum class 声明一种类型,其中包含一组固定的值,即它的常量。每个常量都是枚举的一个对象,具有 name 和 ordinal,其中 ordinal 表示它从 0 开始的位置。entries 会按顺序列出这些常量:
enum class Direction { NORTH, EAST, SOUTH, WEST }在 main 中:
val d = Direction.EAST
println(d)
println(d.ordinal)
println(Direction.entries)输出:
EAST
1
[NORTH, EAST, SOUTH, WEST]枚举常量可以拥有属性,这些属性会传递给枚举的构造函数;枚举也可以声明方法。分号用于在成员前结束常量列表:
enum class Coin(val cents: Int) {
PENNY(1), NICKEL(5), DIME(10), QUARTER(25);
fun label() = "${name.lowercase()} ($cents c)"
}在 main 中:
println(Coin.DIME.label())
println(Coin.entries.sumOf { it.cents })输出:
dime (10 c)
41当 when 处理了列出每个常量的枚举时,就不需要 else,编译器会报告缺少的常量。valueOf("SOUTH") 会按精确名称查找常量,遇到未知名称时会抛出异常,因此通常会用 entries.find 匹配输入:
enum class Direction { NORTH, EAST, SOUTH, WEST }
fun turnRight(d: Direction) = when (d) {
Direction.NORTH -> Direction.EAST
Direction.EAST -> Direction.SOUTH
Direction.SOUTH -> Direction.WEST
Direction.WEST -> Direction.NORTH
}
fun parse(text: String) = Direction.entries.find { it.name == text.uppercase() }在 main 中:
println(turnRight(Direction.valueOf("SOUTH")))
println(parse("north"))
println(parse("up"))输出:
WEST
NORTH
null常量可以有自己的主体,并在其中重写方法。在枚举中将方法声明为 abstract,会强制每个常量都实现它:
enum class Op(val symbol: String) {
PLUS("+") {
override fun apply(a: Int, b: Int) = a + b
},
TIMES("*") {
override fun apply(a: Int, b: Int) = a * b
};
abstract fun apply(a: Int, b: Int): Int
}在 main 中:
for (op in Op.entries) println("6 ${op.symbol} 3 = ${op.apply(6, 3)}")输出:
6 + 3 = 9
6 * 3 = 18挑战
简单完成枚举 Size,包含常量 SMALL(250 ml,价格为 300)、MEDIUM(350 ml,380)和 LARGE(500 ml,450),价格单位为分。label() 返回 medium (350 ml): 3.80,upsize() 返回下一个更大的尺寸,如果是 LARGE,则返回相同的尺寸。伴生对象的 parse(text) 会忽略大小写,按名称查找尺寸,或按首字母查找(s、M),否则返回 null。
提供的代码会读取类似 medium、L 或 up small(加大后的饮品)的订单,并打印每个标签或 unknown size x,最后打印 total: 11.10。
你的代码写在 Size.kt 中。Main.kt 包含提供的输入/输出代码,不能编辑。
亲手试试
fun main() {
// 提供的输入和输出代码:保持原样。
val input = generateSequence(::readLine).toList()
var total = 0
for (line in input) {
val upsize = line.startsWith("up ")
val size = Size.parse(line.removePrefix("up "))
if (size == null) {
println("unknown size $line")
continue
}
val chosen = if (upsize) size.upsize() else size
println(chosen.label())
total += chosen.price
}
println("total: %d.%02d".format(total / 100, total % 100))
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Kotlin 在线编辑器