美文网首页
Kotlin密封类

Kotlin密封类

作者: Vincent_f610 | 来源:发表于2019-03-17 12:14 被阅读0次

什么是密封类

密封类用来表示受限的类继承结构:当一个值为有限集中的类型、而不能有任何其他类型时。

以上是官网介绍;一脸蒙逼.jpg

举个栗子,动物有哺乳动物,爬行动物,鸟类,鱼类,等等;用动物分类写一个密封类:

密封类 动物 Animal

子类 鸟类 继承 动物 Bird:Animal()

子类 鱼类 继承 动物 Fish:Animal()

转换成代码:

sealed class Animal

class Bird(var name: String) : Animal()
class Fish(var name: String) : Animal()

密封类特性

  • 声明一个密封类在类名使用 sealed 修饰符
  • 所有子类都必须在与密封类自身相同的文件中声明(子类的扩展类不受此控制)
  • 一个密封类是自身抽象的,它不能直接实例化并可以有抽象(abstract)成员
  • 密封类不允许有非-private 构造函数(其构造函数默认为 private)

再次蒙逼.jpg
不急,查看kotlin字节码

怎么查看?AndroidStudio-->Tools-->Kotlin-->Show Kotlin ByteCode

Animal 字节码

public abstract class com/example/mykoltin/Animal {


  // access flags 0x2
  private <init>()V//私有构造方法
   ...

  @Lkotlin/Metadata;(mv={1, 1, 13}, bv={1, 0, 3}, ...
}

Animal类使用abstract修饰符声明;private <init>()V 构造函数私有,意味着不能直接创建实例;也不能被其它类继承,那么Bird是怎么继承Animal的呢?

Bird类

public final class com/example/mykoltin/Bird extends com/example/mykoltin/Animal  {
 
  // access flags 0x1
  public <init>(Ljava/lang/String;)V
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ...
   L1
    LINENUMBER 9 L1
    ALOAD 0
    ACONST_NULL
    INVOKESPECIAL com/example/mykoltin/Animal.<init> (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
    ALOAD 0
    ALOAD 1
    PUTFIELD com/example/mykoltin/Bird.name : Ljava/lang/String;
    RETURN
   L2
    ...

  
}

Bird类构造方法调用了Animal构造方法,等下Animal不是私有的构造方法吗?

INVOKESPECIAL com/example/mykoltin/Animal.<init> (Lkotlin/jvm/internal/DefaultConstructorMarker;)V

Bird类继承Animal后; Animal字节码

public abstract class com/example/mykoltin/Animal {


  // access flags 0x2
  private <init>()V//私有构造方法
   ...

  // access flags 0x1001
  public synthetic <init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V//公共构造方法
  ...

  @Lkotlin/Metadata;(mv={1, 1, 13}, bv={1, 0, 3}, ...
}

Animal多了一个public构造方法,这个方法里面调用了自身私有构造方法,所以Bird是调用了Animal public构造方法实现继承的,一切都水落石出了。

使用场景

fun main(args: Array<String>) {
    val animalName = getAnimalName(Fish("鲨鱼"))
    print(animalName)
}
fun getAnimalName (animal:Animal):String =when(animal){
    is Bird -> "鸟类:"+animal.name
    is Fish -> "鱼类:"+animal.name
}

sealed class Animal

class Bird(var name: String) : Animal()
class Fish(var name: String) : Animal()

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

小结

密封类与枚举类有什么区别?

密封类在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例

还是用上文中动物分类举例,动物分类有鱼类,鸟类...;鱼类又分为鲨鱼类等,鲨鱼类又分大白鲨,虎鲨,锤头鲨,长尾鲨...(ps非严谨分类勿较真);这种情况用枚举就不太合适,因为密封类它的子类实例是可数的,也就是包含了多个实例。

class Shark(name: String) : Fish(name)

参考&引用

kotlin文档-密封类

kotlin入门潜修之类和对象篇—密封类及其原理

相关文章

  • Android MVI 设计模式(3)

    我们用 kotlin 的 sealed 类密封一些数据类,kotlin 提供的密封类类似于枚举,密封类用于定义一种...

  • Kotlin学习之密封类

    Kotlin学习之密封类 密封类是Kotlin中的一个高级类,有如下特点: 密封类是为继承设计的,是一个抽象类; ...

  • Kotlin密封类

    什么是密封类 密封类用来表示受限的类继承结构:当一个值为有限集中的类型、而不能有任何其他类型时。 以上是官网介绍;...

  • Kotlin 密封类 Sealed的总结

    概念sealed修饰的类 在kotlin中是密封类 密封类 描述的是 父类和子类的关系1、密封类和它的子类必须定义...

  • kotlin sealed密封类

    kotlin中sealed关键字修饰的类就是密封类。密封类其实是一种特殊的抽象类,专门用于派生子类的。 密封类的特...

  • kotlin 密封类(sealed)

    class 基类名称sealed class 基类名称 {class 子类1class 子类2}这样,这个基类就变...

  • Kotlin继承与多态 (3)密封类

      如果一个类的子类个数是有限的,那么 kotlin 中可以把这种父类定义为密封类,密封类是一种抽象类,它限定了子...

  • 33. 密封类

    密封类是 kotlin 中比较特殊的类,用来表示受限的类继承结构。它的值为有限集内的类型,不能有任何其他类型。密封...

  • Kotlin 数据类与密封类

    数据类 我们经常创建一些只保存数据的类。在这些类中,一些标准函数往往是从数据机械推导而来的。Kotlin 中使用关...

  • Kotlin 数据类与密封类

    数据类 Kotlin 可以创建一个只包含数据的类,关键字为 data: 编译器会自动的从主构造函数中根据所有声明的...

网友评论

      本文标题:Kotlin密封类

      本文链接:https://www.haomeiwen.com/subject/qcflmqtx.html