Kotlin学习系列——密封类

今天说说Kotlin中的密封类。

在Java中没有密封类这个概念,所以就没法和Java进行对比了,主要看看Kotlin中的密封类的出现目的和使用方法。

为什么会出现密封类

我们先不说密封类是什么,先看看为什么需要密封类。下面先通过一段代码来看。

Kotlin代码

interface FatherClass
class SonClass1: FatherClass{

}

class SonClass2: FatherClass{

}

fun check(fatherClass: FatherClass): String =
    when(fatherClass){
        is SonClass1 -> "1"
        is SonClass2 -> "2"
        else ->
                throw IllegalArgumentException("Unknown Class")
    }

fun main(args: Array<String>){
    val son1 = SonClass1();
    val result = check(son1)
    println(result)
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

上面的代码中定义了一个接口,然后两个类实现这个接口。我们在check方法中通过传入接口对象,使用when来判断传入的对象是哪种类型。关于when的使用,可以查看以前的文章有专门介绍。这里使用when时,必须要添加一个else分支,否则会报错,无法编译通过。

但是上面的代码存在一个潜在的问题。假如我们这时候再添加一个子类,这时候when并没有发现我们的子类增加了,也不会报错,可能我们需要给when增加一个新的分支,但是由于没有报错,可能就会被我们忽略了。

基于上面的原因,Kotlin为了解决上面的潜在问题,便提出了密封类

密封类的使用

密封类需要使用sealed关键字修饰,并且被sealed关键字修饰的类,它的子类必须要以嵌套类的形式在父类中全部声明,关于嵌套类的想关内容可以查看上一节的文章。下面写一个密封类的例子。

sealed class SealedClass{
    class SonClass1: SealedClass(){

    }

    class SonClass2: SealedClass(){

    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如果你看过前面的内容,你就会有疑问,Kotlin中的类不是默认final的吗?为什么可以被继承呢?
这是因为被sealed修饰的类默认是open的,所以可以被继承,而不需要显式使用open修饰符。

那我看看密封类的出现,会怎么解决我们上面提出的问题呢?看下面的代码

Kotlin代码

sealed class SealedClass{
    class SonClass1: SealedClass(){

    }

    class SonClass2: SealedClass(){

    }
}

fun check(sealedClass: SealedClass): String =
    when(sealedClass){
        is SealedClass.SonClass1 -> "1"
        is SealedClass.SonClass2 -> "2"
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

你会发现when结构中少了else分支。对因为在密封类中已经列出了所有的密封类的所有子类,所以就不会有else的情况。
这样之后,你每次增加一个子类,when结构就会检查到你增加了子类,就必须要给when结构添加一个分支,否则就会编译报错,这样就把潜在的问题消灭在了编译阶段。
就像下面这样,增加一个子类必须增加相应的when分支

Kotlin代码

package kt

sealed class SealedClass{
    class SonClass1: SealedClass(){

    }

    class SonClass2: SealedClass(){

    }

    class SonClass3: SealedClass(){

    }
}

fun check(sealedClass: SealedClass): String =
    when(sealedClass){
        is SealedClass.SonClass1 -> "1"
        is SealedClass.SonClass2 -> "2"
        is SealedClass.SonClass3 -> "3"
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
写在最后
1. 密封类用于表示受限制的类层次结构,当一个值只能在一个集合中取值时,而不能取其他值时。在某种意义上,这是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。 但是所有的子类必须和父类生命在同一个文件中。

2.需要注意的是,密封类的非直接继承的子类可以声明在其他文件中。

3.密封类的主要好处在于使用when表达式。如果能够验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。

Kotlin中的密封类的出现,在于它定义了一种受限的类继承结构,可以保证我们写出更安全的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值