美文网首页述术
kotlin-sealed classes

kotlin-sealed classes

作者: 请输入妮称 | 来源:发表于2018-08-20 08:22 被阅读36次

    sealed classes是一堆存在继承关系的类的集合。

    类似于java中的枚举。不同的是,每个枚举类型只能存在一个对象实例,
    而sealed class的子类可以拥有多个对象实例。

    sealed关键字用来修饰sealed class。
    sealed class的子类必须声明在同一个文件中。
    但是sealed class的子类的子类可以定义在任何位置。

    sealed class Expr
    data class Const(val number: Double) : Expr()
    data class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
    

    类Expr是抽象类,可以声明抽象变量、方法等,所以不能被实例化。
    Expr的构造方法默认是private修饰的,并且不能修改。

    当我们使用when表达式的时候,传入的参数如果是Expr类型,则可以智能推断出是否覆盖了所有的条件。

    fun eval(expr: Expr): Double = when(expr) {
        is Const -> expr.number
        is Sum -> eval(expr.e1) + eval(expr.e2)
        NotANumber -> Double.NaN
    }
    

    上述例子不再需要else语句了,因为编译器推断出expr只能为Const、Sum或者NotANumber。

    我们反编译sealed class来查看一下真面目:

    // Sum.java
    import kotlin.Metadata;
    import kotlin.jvm.internal.DefaultConstructorMarker;
    import kotlin.jvm.internal.Intrinsics;
    import org.jetbrains.annotations.NotNull;
    
    @Metadata(
       mv = {1, 1, 10},
       bv = {1, 0, 2},
       k = 1,
       d1 = {"\u0000$\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\n\n\u0002\u0010\u000b\n\u0000\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u000e\n\u0000\b\u0086\b\u0018\u00002\u00020\u0001B\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0001\u0012\u0006\u0010\u0003\u001a\u00020\u0001¢\u0006\u0002\u0010\u0004J\t\u0010\b\u001a\u00020\u0001HÆ\u0003J\t\u0010\t\u001a\u00020\u0001HÆ\u0003J\u001d\u0010\n\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00012\b\b\u0002\u0010\u0003\u001a\u00020\u0001HÆ\u0001J\u0013\u0010\u000b\u001a\u00020\f2\b\u0010\r\u001a\u0004\u0018\u00010\u000eHÖ\u0003J\t\u0010\u000f\u001a\u00020\u0010HÖ\u0001J\t\u0010\u0011\u001a\u00020\u0012HÖ\u0001R\u0011\u0010\u0002\u001a\u00020\u0001¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006R\u0011\u0010\u0003\u001a\u00020\u0001¢\u0006\b\n\u0000\u001a\u0004\b\u0007\u0010\u0006¨\u0006\u0013"},
       d2 = {"LSum;", "LExpr;", "e1", "e2", "(LExpr;LExpr;)V", "getE1", "()LExpr;", "getE2", "component1", "component2", "copy", "equals", "", "other", "", "hashCode", "", "toString", "", "production sources for module app"}
    )
    public final class Sum extends Expr {
       @NotNull
       private final Expr e1;
       @NotNull
       private final Expr e2;
    
       @NotNull
       public final Expr getE1() {
          return this.e1;
       }
    
       @NotNull
       public final Expr getE2() {
          return this.e2;
       }
    
       public Sum(@NotNull Expr e1, @NotNull Expr e2) {
          Intrinsics.checkParameterIsNotNull(e1, "e1");
          Intrinsics.checkParameterIsNotNull(e2, "e2");
          super((DefaultConstructorMarker)null);
          this.e1 = e1;
          this.e2 = e2;
       }
    
       @NotNull
       public final Expr component1() {
          return this.e1;
       }
    
       @NotNull
       public final Expr component2() {
          return this.e2;
       }
    
       @NotNull
       public final Sum copy(@NotNull Expr e1, @NotNull Expr e2) {
          Intrinsics.checkParameterIsNotNull(e1, "e1");
          Intrinsics.checkParameterIsNotNull(e2, "e2");
          return new Sum(e1, e2);
       }
    
       // $FF: synthetic method
       // $FF: bridge method
       @NotNull
       public static Sum copy$default(Sum var0, Expr var1, Expr var2, int var3, Object var4) {
          if ((var3 & 1) != 0) {
             var1 = var0.e1;
          }
    
          if ((var3 & 2) != 0) {
             var2 = var0.e2;
          }
    
          return var0.copy(var1, var2);
       }
    
       public String toString() {
          return "Sum(e1=" + this.e1 + ", e2=" + this.e2 + ")";
       }
    
       public int hashCode() {
          return (this.e1 != null ? this.e1.hashCode() : 0) * 31 + (this.e2 != null ? this.e2.hashCode() : 0);
       }
    
       public boolean equals(Object var1) {
          if (this != var1) {
             if (var1 instanceof Sum) {
                Sum var2 = (Sum)var1;
                if (Intrinsics.areEqual(this.e1, var2.e1) && Intrinsics.areEqual(this.e2, var2.e2)) {
                   return true;
                }
             }
    
             return false;
          } else {
             return true;
          }
       }
    }
    // NotANumber.java
    import kotlin.Metadata;
    import kotlin.jvm.internal.DefaultConstructorMarker;
    
    @Metadata(
       mv = {1, 1, 10},
       bv = {1, 0, 2},
       k = 1,
       d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\bÆ\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
       d2 = {"LNotANumber;", "LExpr;", "()V", "production sources for module app"}
    )
    public final class NotANumber extends Expr {
       public static final NotANumber INSTANCE;
    
       private NotANumber() {
          super((DefaultConstructorMarker)null);
       }
    
       static {
          NotANumber var0 = new NotANumber();
          INSTANCE = var0;
       }
    }
    // Expr.java
    import kotlin.Metadata;
    import kotlin.jvm.internal.DefaultConstructorMarker;
    
    @Metadata(
       mv = {1, 1, 10},
       bv = {1, 0, 2},
       k = 1,
       d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0000\b6\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002\u0082\u0001\u0003\u0003\u0004\u0005¨\u0006\u0006"},
       d2 = {"LExpr;", "", "()V", "LConst;", "LSum;", "LNotANumber;", "production sources for module app"}
    )
    public abstract class Expr {
       private Expr() {
       }
    
       // $FF: synthetic method
       public Expr(DefaultConstructorMarker $constructor_marker) {
          this();
       }
    }
    // Const.java
    import kotlin.Metadata;
    import kotlin.jvm.internal.DefaultConstructorMarker;
    import org.jetbrains.annotations.NotNull;
    
    @Metadata(
       mv = {1, 1, 10},
       bv = {1, 0, 2},
       k = 1,
       d1 = {"\u0000*\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u0006\n\u0002\b\u0006\n\u0002\u0010\u000b\n\u0000\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u000e\n\u0000\b\u0086\b\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\t\u0010\u0007\u001a\u00020\u0003HÆ\u0003J\u0013\u0010\b\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u0003HÆ\u0001J\u0013\u0010\t\u001a\u00020\n2\b\u0010\u000b\u001a\u0004\u0018\u00010\fHÖ\u0003J\t\u0010\r\u001a\u00020\u000eHÖ\u0001J\t\u0010\u000f\u001a\u00020\u0010HÖ\u0001R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\u0011"},
       d2 = {"LConst;", "LExpr;", "number", "", "(D)V", "getNumber", "()D", "component1", "copy", "equals", "", "other", "", "hashCode", "", "toString", "", "production sources for module app"}
    )
    public final class Const extends Expr {
       private final double number;
    
       public final double getNumber() {
          return this.number;
       }
    
       public Const(double number) {
          super((DefaultConstructorMarker)null);
          this.number = number;
       }
    
       public final double component1() {
          return this.number;
       }
    
       @NotNull
       public final Const copy(double number) {
          return new Const(number);
       }
    
       // $FF: synthetic method
       // $FF: bridge method
       @NotNull
       public static Const copy$default(Const var0, double var1, int var3, Object var4) {
          if ((var3 & 1) != 0) {
             var1 = var0.number;
          }
    
          return var0.copy(var1);
       }
    
       public String toString() {
          return "Const(number=" + this.number + ")";
       }
    
       public int hashCode() {
          long var10000 = Double.doubleToLongBits(this.number);
          return (int)(var10000 ^ var10000 >>> 32);
       }
    
       public boolean equals(Object var1) {
          if (this != var1) {
             if (var1 instanceof Const) {
                Const var2 = (Const)var1;
                if (Double.compare(this.number, var2.number) == 0) {
                   return true;
                }
             }
    
             return false;
          } else {
             return true;
          }
       }
    }
    
    

    相关文章

      网友评论

        本文标题:kotlin-sealed classes

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