Kotlin开发指南Kotlin编程禅与计算机程序设计艺术

枚举和"when"

2018-09-28  本文已影响1人  墨白历险记

废话少说,先上代码.

枚举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表达式提供参数,分支条件就是任意的布尔表达式.但这种写法会造成代码的可读性变差,可这是为了达到更好的性能而必须付出的代价.

上一篇 下一篇

猜你喜欢

热点阅读