Kotlin学习 - 枚举和密封类

在文章Kotlin学习 - 选择控制if 和when中有一句话:如果 when 作为一个表达式使用,则必须有 else 分支,因为Kotlin编译器会强制检查默认选项 ,除非编译器能够检测出所有的可能情况都已经覆盖了。 那什么情况下编译器能检测出所有的情况呢?就是本文章标题的两个种情况,枚举和密封类。

枚举

enum class Color{
    RED,GREEN,BLUE,YELLOW
}

这里使用《Kotlin实战》书中的例子,新建一个枚举类Color,和Java一样可以给枚举类声明属性和方法。

enum class Color(val r: Int, val g: Int, val b: Int) {
    RED(255, 0, 0), GREEN(0, 255, 0),
    BLUE(0, 0, 255), YELLOW(255, 255, 0);
    
    fun getRgb() = (r * 256 + g) * 256 + b
}

新建一个Color枚举类,属性有三个rgb,使用主构造函数进行了声明,getRgb是类中定义的方法。

使用when处理枚举

fun getColorMeaning(color: Color) = when (color){
    Color.RED -> "passion"
    Color.GREEN -> "vitality"
    Color.BLUE -> "unhappy"
    Color.YELLOW -> "happy"
}

上面代码有啥特点呢?

  • 没有else分支,如果when中分支条件都是枚举类型,不需要else分支;
  • 枚举中所有定义的类型需要在分支中全部列出,否则会报错;

调用代码:

fun main() {
  println(getColorMeaning(Color.RED))
}

//结果
passion

密封类-sealed

定义个请求结果类型接口Result,结果只有两种成功或者失败,定义如下:

interface Result 
class Success(val msg: String) : Result
class Failure(val msg: String) : Result

再定义一个获取结果的方法:

fun getResultMsg(result: Result) = when(result) {
    is Success -> result.msg
    is Failure -> result.error.message
    else -> throw IllegalArgumentException()
}

由于Kotlin编译器会强制检查默认选项,所以when分支中必须有else,因此就算只有两个结果,也必须写else,在这个例子中默认值不能返回一个有意义的值,因此会抛出一个异常。

总是不得不添加一个默认分支很不方便,尤其是添加一个新的子类的时候,如果忘记在when中添加分支,编译器也没有任何提示,就会走到默认分支,抛出异常。

Kotlin提供解决方案-sealed类,在类前面加上该修饰符,对所有可能创建的子类进行限定,直接子类必须嵌套在父类中。(我看其他博客可以写在外面,这里为了好理解,放在了密封类中)

sealed class Result{
    class Success(val msg: String) : Result()
    class Failure(val error: Exception) : Result()
}

方法修改如下:

fun getResultMsg(result: Result) = when (result) {
    is Result.Success -> result.msg
    is Result.Failure -> result.error.message
}

此时去掉else即可,但是分支必须包括密封类的全部子类,否则编译不通过。

你可能感兴趣的:(kotlin,kotlin,学习,android)