kotlin-sealed classes

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;
      }
   }
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 我先翻譯為密封類吧O__O "…。 什么是密封類? 官方文檔:密封類用于表示受限類的層次結構,當一個值有一個有限的...
    Kotyo閱讀 892評論 0 1
  • 面向對象編程(OOP) 在前面的章節中,我們學習了Kotlin的語言基礎知識、類型系統、集合類以及泛型相關的知識。...
    Tenderness4閱讀 4,479評論 1 6
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發現簡書還為我保存起的...
    Jenaral閱讀 2,830評論 2 9
  • 原題 檢查一棵二叉樹是不是完全二叉樹。完全二叉樹是指一棵樹除了最后一層,其它層上節點都有左右孩子,最后一層上,所有...
    Jason_Yuan閱讀 467評論 0 0
  • 之所以會想寫這篇文章,主要是今天下午的一個見聞,發生在駕校練車場地的一個小插曲。 故事的主人公是一個2...
    思齊001閱讀 378評論 0 1