前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kotlin实战【三】表示与选择

Kotlin实战【三】表示与选择

作者头像
先知先觉
发布2019-01-21 15:29:21
6120
发布2019-01-21 15:29:21
举报

前言

本章我们将学习怎么样在Kotlin中通过枚举和when实现表示与选择。

一 、表示与选择之枚举

1.1枚举的定义

我们来看一下java中的用法:

代码语言:javascript
复制
public enum Color
{
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}

kotlin中的用法:

代码语言:javascript
复制
enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}

你会发现kotlin中使用enum同时还要使用class这与java中不同,思考下这是为什么?

知识点

  • 在Kotlin中,enum就是所谓的软关键词(soft keyword):当它放置在class关键词之前,它才有特有的意义。但是你可以在其他的地方,把它当成常规的名字使用。
  • class仍然是一个关键字,要继续使用clazzName之类的来声明变量。

与java相同,枚举中可以声明属性和方法

1.2 带属性的枚举类

先看看java中的代码:

代码语言:javascript
复制
public enum Color
{
    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);

    private int r;
    private int g;
    private int b;

    Color(int r, int g, int b)
    {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public int getRGB(){
        return (r * 256 + g * 256 + b*256);
    }

    public int getR()
    {
        return r;
    }

    public int getG()
    {
        return g;
    }

    public int getB()
    {
        return b;
    }
}

是不是超级多,再来看看kotlin,是不是少了好多,瞬间清爽了很多

代码语言:javascript
复制
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 * 256 + g * 256 + b*256)//定义枚举的方法
}

从两个例子中可以看出,当你定义一个枚举常量,你需要为它提供属性值。

这个例子中展示了Kotlin语法唯一需要分号的地方:在枚举类中如果你定义任何方法,分号区分了枚举常量列表和方法声明。

接下来我们看一下枚举的处理:

二 、表示与选择之When

2.1 使用“when”来处理枚举

接下来我们使用when选择枚举,我们输入一个颜色,返回对应的一个字符串

代码语言:javascript
复制
fun getMnemonic(color: Color) =   //直接返回一个“when”的表达式
    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

上面代码我们可以处,你不需要为每个分支写break语句(在java中遗漏break通常会导致bug)。

可以吧多个值合并到同一个分支,只需要逗号隔开。

如下:

代码语言:javascript
复制
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枚举类名。你可以用导入常量来简化代码:

代码语言:javascript
复制
import ch02.colors.Color //导入声明在另外一个包的Color类
import ch02.colors.Color.*//用名字显示导入枚举常量

fun getWarmth(color: Color) = when(color) {
    RED, ORANGE, YELLOW -> "warm" //用名字导入常量
    GREEN -> "neutral"
    BLUE, INDIGO, VIOLET -> "cold"
}

2.2 在"when"结构中使用任意对象

kotlin中的when结构比java中的switch强大得多。switch必须要求使用常量(枚举常量、字符串或者数字字面值)作为分支条件,而when可以使用任何对象。

下面我们写一个混合两者颜色的函数:

代码语言:javascript
复制
fun mix(c1: Color, c2: Color) =
    when (setOf(c1, c2)) {//when表达式的参数可以是任何实例,用来被分支条件检查
        setOf(RED, YELLOW) -> ORANGE//枚举可以混合的颜色对
        setOf(YELLOW, BLUE) -> GREEN
        setOf(BLUE, VIOLET) -> INDIGO
        else -> throw Exception("Dirty color")//执行这个,如果没有分支可以匹配
    }
println(mix(BLUE, YELLOW))//GREEN

Kotlin标准库中含有一个setOf的函数,用来创建Set,包含参数指定的实例;一个set是一个集合,它的项的次序并不重要。所以,如果setOf(c1, c2)和setOf(RED, YELLOW)是相等的,那么意味着要不然c1是RED和c2是YELLOW,或者相反。

2.3 使用不带参数的when

上面的例子有点效率低下,因为每次你调用这个函数,它都会创建几个Set实例,仅仅是用在检查两个颜色是否匹配另外两个颜色。正常情况下,通常不是个问题。但是如果这个函数经常被调用,那么为了避免GC,值得用另外一种方式来重写这个代码。你可以用不带参数的when表达式完成。代码虽然可读性差一点,但是这是为了达到更好性能付出的代价。

代码语言:javascript
复制
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) || (c1 == VIOLET && c2 == BLUE) -> INDIGO
        else -> throw Exception("Dirty color")
    }
println(mixOptimized(BLUE, YELLOW)) //GREEN

2.4 代码块作为"if"和"when"的分支

if和when都可以用代码块作为分支。

在这个例子中,代码块中最后最后一个表达式作为结果。如果你想在例子函数中加日志,你可以在代码块中完成,并用最后一个值返回。

代码语言:javascript
复制
fun evalWithLogging(e: Expr): Int =
    when (e) {
        is Num -> {
            println("num: ${e.value}")
            e.value //如果e是Num类型,这是代码块最后一个表达式,并被返回
        }
        is Sum -> {
            val left = evalWithLogging(e.left)
            val right = evalWithLogging(e.right)
            println("sum: $left + $right")
            left + right//如果表达式被返回当e是Sum类型
        }
        else -> throw IllegalArgumentException("Unknown expression")
    }
    println(evalWithLogging(Sum(Sum(Num(1), Num(2)), Num(4))))
    //num: 1
    //num: 2
    //sum: 1 + 2
    //num: 4
    //sum: 3 + 4
    //7

规则 :“代码块中最后一个表达式是返回值”,在所有使用代码块并期望得到一个结果的地方成立。

现在已经学会了如何正确从众多选项中作出选择,下一章我们一起去看下如何迭代事物。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年09月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一 、表示与选择之枚举
    • 1.1枚举的定义
      • 1.2 带属性的枚举类
      • 二 、表示与选择之When
        • 2.1 使用“when”来处理枚举
          • 2.2 在"when"结构中使用任意对象
            • 2.3 使用不带参数的when
              • 2.4 代码块作为"if"和"when"的分支
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档