Kotlin实战3-枚举和when

声明枚举类

声明一个简单的枚举类

1
2
3
enum class Food {
FRUID, WATER, NOODLE
}

Kotlin用了enum class两个关键字来声明枚举类,而java只用了enum一个关键字。在Kotlin中,enum是一个软关键字 :只有当它出现在class前面时才有特殊的意义,在其他地方可以把它当成普通的名称使用。

声明一个带属性的枚举类

1
2
3
4
5
6
7
8
9
enum class Color(val r: Int, val g: Int, val b: Int) { // 声明枚举常量的属性
// 在每个常量创建的时候指定属性值
RED(255, 0, 0), ORANGE(255, 165, 0), YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),INDIGO(75, 0, 130), VIOLET(238, 130, 238);
// 给枚举类定义一个方法
fun rgb() = (r * 255 + g) * 255 + b
}
// 输出
>>> println(Color.BLUE.rgb())
>>> 255

如果要在枚举类中定义任何方法,都要使用分号 把枚举常量列表和方法定义分开,这是Kotlin语法中唯一必须使用分号的地方。

使用”when”处理枚举类

在Kotlin中,与java的switch相对应的结构,是when。和if相似,when是一个有返回值的表达式,因此可以写一个直接返回when表达式的表达式体函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 直接返回when表达式
fun getMnemonic(color: Color) =
when (color) {
Color.RED -> "Richard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Gave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
// 输出
>>> println(getMnemonic(Color.BLUE))
>>> Battle

和java不一样的是,不需要在每个分支都写上break语句,如果匹配成功,只有对应的分支会执行,也可以把多个分支的值合并到同一个分支,只需要用逗号隔开这些值。

1
2
3
4
5
6
7
8
9
fun getWarmth(color: Color) =
when (color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
Color.GREEN -> "neutral"
Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
// 输出
>>> println(getWarmth(Color.ORANGE))
>>> warm

这些例子使用了枚举常量的完整名称,即指定了枚举类的名称Color,可以通过导入这些常量来简化代码。

1
2
3
4
5
6
fun getWarmth(color: Color) =
when (color) {
RED, ORANGE, YELLOW -> "warm"
GREEN -> "neutal"
BLUE, INDIGO, VIOLET -> "cold"
}

在”when”结构中使用任意对象

Kotlin中的when结构比java中的switch要强大得多。switch要求必须使用常量(枚举常量,字符串或者数字字面量)作为分支条件,when允许使用任意对象

1
2
3
4
5
6
7
8
9
10
fun mix(c1: Color, c2: Color) =
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
else -> throw Exception("Dirty color")
}
// 输出
>>> println(mix(VIOLET, BLUE).ordinal)
>>> INDIGO

Kotlin标准函数库中有一个setOf函数可以创建出一个Set,它会包含所有指定为函数实参的对象。set集合的条目顺序并不重要,只要两个set包含一样的条目,它们就是相等的。

使用不带参数的”when”

上面的方法,在每次调用这个函数的时候,都会创建一些Set实例,仅仅用来检查两种给定的颜色是否和另外的颜色匹配,如果这个函数调用频繁,可以使用另外一种方式,来避免创建额外的垃圾对象。代码可读性会变差,但是能达到更好的性能。

1
2
3
4
5
6
7
fun mixOptimized(c1: Color, c2: Color) =
when { //没有实参传给when
(c1 == RED && c2 == YELLOW) || (c1 == YELLOW && c2 == RED) -> ORANGE
(c1 == YELLOW && c2 == BLUE) || (c1 == BLUE && c2 == YELLOW) -> GREEN
(c1 == BLUE && c2 == VIOLET) || (c2 == VIOLET && c1 == BLUE) -> INDIGO
else -> throw Exception("Dirty color")
}
0%