枚举和"when"
废话少说,先上代码.
枚举enum
# java
public enum Num {
ONE, TWO, THREE
}
# kotlin
enum class Num {
ONE, TWO, THREE
}
在kotlin中,enum是一个软关键字,只有当他出现在class前面是才有特殊的意义,在其他地方可以当成普通的名称使用.
在枚举中声明方法
enum class Color(val r: Int, val g: Int, val b: Int) {
RED(255, 0, 0),
YELLOW(255, 255, 0),
BLUE(0, 0, 255);
fun rgb() = (r * 256 + g) * 256 + b
}
fun main(args: Array<String>) {
println(Color.BLUE)
println(Color.BLUE.r)
println(Color.BLUE.rgb())
}
打印结果:
>>> BLUE
>>> 0
>>> 255
当声明每个枚举常量时,必须提供该常量的属性值.
在枚举中声明方法是kotlin语法中中唯一必须使用";"的地方,需要使用分号将枚举常量列表和方法定义分开.
使用"when"处理枚举
豪宅、美女、豪车,这些都是屌丝男的梦想,但是很多国外的汽车品牌都是英文的,那现在我们想要写一个函数来对应中文的名字,但我们不想把这些名字存储在枚举内部,我们该如何处理呢?
在Java中我们首先会想到switch,而Kotlin中对应的语法结构是when.
接下来我们演示一下,首先定义一个汽车类的枚举.
enum class Car {
JEEP, VOLVO, BENX, BMW
}
fun getChineseName(car: Car) =
when (car) {
Car.JEEP -> "吉普"
Car.VOLVO -> "沃尔沃"
Car.BENX -> "奔驰"
Car.BMW -> "宝马"
}
fun main(args: Array<String>) {
println(getChineseName(Car.BENX))
}
打印结果:
>>> 奔驰
上面的代码根据传进来的car值找到对应的分支并执行相应的逻辑.与java中不同的是,不需要在每个分支都编写break语句.匹配成功只会执行对应的分支逻辑.也可以将多个值合并到同一个分支.需要用逗号隔开.
fun getChineseName(car: Car) =
when (car) {
Car.JEEP,
Car.VOLVO,
Car.BENX
-> "外国汽车"
Car.BMW -> "宝马"
}
fun main(args: Array<String>) {
println(getChineseName(Car.BENX))
}
打印结果:
>>> 外国汽车
在when中使用"任意"对象
在java的switch中,判断的条件值只可以使用枚举常量、字符串、数字字面值,而在kotlin中,when允许使用任何对象.
接下来就是吃货的福音啦~
我们写一个菜谱,任意的两种菜品组合,然后可以做出什么菜.
enum class Vegetables {
EGG, TOMATO, PORK, BEEF, POTATO
}
fun makeFood(vegetables1: Vegetables, vegetables2: Vegetables) =
when (setOf(vegetables1, vegetables2)) {
setOf(Vegetables.BEEF, Vegetables.POTATO) -> "土豆炖牛肉"
setOf(Vegetables.BEEF, Vegetables.TOMATO) -> "番茄牛腩"
setOf(Vegetables.EGG, Vegetables.TOMATO) -> "番茄炒蛋"
else -> "乱炖"
}
fun main(args: Array<String>) {
println(makeFood(Vegetables.BEEF,Vegetables.POTATO))
println(makeFood(Vegetables.EGG,Vegetables.POTATO))
}
打印结果:
>>> 土豆炖牛肉
>>> 乱炖
我们使用set来实现了这个菜谱,在Kotlin的标准函数库中有一个setof()函数可以创建出一个set.它会包含所有指定为函数实参的对象并且顺序没有要求,只要两个set中包含相同的条目,他们就是相等的.
when表达式将它的所有实参依次和所有分支匹配,知道某个分支满足条件,就会开始执行.如果没有符合条件的分支,则会执行else的分支.
使用不带参数的when
有细心的朋友可能会觉得上面的做菜函数效率有点低,每次调用这个函数他都会去创建一些set实例,仅仅只是用来检查两种给定的菜品是否和另外两种匹配.正常的情况下可能没什么,但是如果这个函数的调用比较频繁,那就应该用一种可以避免创建额外的垃圾对象的方式来进行编写.
有码有真相哦~
fun makeFood(vegetables1: Vegetables, vegetables2: Vegetables) =
when {
(vegetables1 == Vegetables.EGG && vegetables2 == Vegetables.TOMATO) ||
(vegetables1 == Vegetables.TOMATO && vegetables2 == Vegetables.EGG)
-> "番茄牛腩"
(vegetables1 == Vegetables.BEEF && vegetables2 == Vegetables.POTATO) ||
(vegetables1 == Vegetables.POTATO && vegetables2 == Vegetables.BEEF)
-> "土豆炖牛肉"
(vegetables1 == Vegetables.EGG && vegetables2 == Vegetables.TOMATO) ||
(vegetables1 == Vegetables.TOMATO && vegetables2 == Vegetables.EGG)
-> "番茄炒蛋"
else -> "乱炖"
}
fun main(args: Array<String>) {
println(makeFood(Vegetables.BEEF,Vegetables.POTATO))
println(makeFood(Vegetables.EGG,Vegetables.POTATO))
}
打印结果:
>>> 土豆炖牛肉
>>> 乱炖
这种方式不会创建额外的对象且执行的结果是一样的,如果没有给when表达式提供参数,分支条件就是任意的布尔表达式.但这种写法会造成代码的可读性变差,可这是为了达到更好的性能而必须付出的代价.