Seal class

Prerequisites:

Kotlin提供Seal class,類似Enum的功能,但看了Java原始碼才發現其實是靜態內部類別。

建立一個密封類別,有三個屬性,全部繼承密封類別。

1
2
3
4
5
sealed class NetworkEvent {
    object Load: NetworkEvent()
    data class Success(val code: Int): NetworkEvent()
    class Error(val errCode:Int, val msg: String) : NetworkEvent()
}

object

建立一個Singleton物件

1
object Load: NetworkEvent()

Kotiln在私下已經建立了Singleton物件。

1
2
3
4
5
class Load private constructor(): NetworkEvent() {
    companion object {
        val INSTANCE = Load()
    }
}

使用Seal Class類別名.屬性,就會自動幫Load屬性,建立好Singleton物件。

1
val loading = NetworkEvent.Load

不能這樣寫。

1
val loading = NetworkEvent.Load()

Java原始碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// NetworkEvent
public abstract class NetworkEvent {
   // 私有建構子
   private NetworkEvent() {
   }

   // 公有建構子
   public NetworkEvent(DefaultConstructorMarker $constructor_marker) {
      this();
   }

   // Load是一個靜態內部類別,且不可以再被繼承final
   // 繼承NetworkEvent
   public static final class Load extends NetworkEvent {
      // 靜態final的Singleton物件
      @NotNull
      public static final Load INSTANCE;

      // 私有建構子
      private Load() {
         // 呼叫父類別的有參數建構子,但傳null進去。
         super((DefaultConstructorMarker)null);
      }

      // 靜態區塊
      static {
         // 類別載入時,就建立Singleton物件
         Load var0 = new Load();
         // var0的記憶體位址 指派 給INSTANCE
         INSTANCE = var0;
      }
   }
}

密封類別的內部類別

1
2
3
4
sealed class NetworkEvent {
    data class Success(val code: Int): NetworkEvent()
    class Error(val errCode:Int, val msg: String) : NetworkEvent()
}

Success與Error是NetworkEvent的內部類別,而且繼承:NetworkEvent()

Java原始碼

Success

因為內部類別Success是Data Class,Data Class本身就會覆寫component、copy、toString、equals等方法,這些方法就先截掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class NetworkEvent {
    .
    .
    .
    // 靜態內部類別,不可被繼承。
   public static final class Success extends NetworkEvent {
      private final int code;

      public final int getCode() {
         return this.code;
      }

      // 建構子
      public Success(int code) {
         super((DefaultConstructorMarker)null);
         this.code = code;
      }
   }
}

Error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class NetworkEvent {
    .
    .
    .
    // 靜態內部類別,不可被繼承。
   public static final class Error extends NetworkEvent {
      // 私有 不可更改 屬性
      private final int errCode;
      @NotNull
      private final String msg;

      public final int getErrCode() {
         return this.errCode;
      }

      @NotNull
      public final String getMsg() {
         return this.msg;
      }
      
      // 建構子
      public Error(int errCode, @NotNull String msg) {
         Intrinsics.checkNotNullParameter(msg, "msg");
         super((DefaultConstructorMarker)null);
         this.errCode = errCode;
         this.msg = msg;
      }
   }
}

判斷與使用

使用when作為判斷

1
2
3
4
5
6
7
fun checkStatus(status: NetworkEvent): String {
    return when(status) {
        is NetworkEvent.Load -> "正在載入中"
        is NetworkEvent.Success -> "成功,code = ${status.code}"
        is NetworkEvent.Error -> "失敗, code = ${status.errCode} , msg = ${status.msg}"
    }
}

測試

1
2
3
4
5
6
7
8
9
10
11
12
fun main() {
    val loading = NetworkEvent.Load
    val success =  NetworkEvent.Success(200)
    val error = NetworkEvent.Error(404, "Page not found")

    var result = checkStatus(success)
    println(result)
    result = checkStatus(error)
    println(result)
    result = checkStatus(loading)
    println(result)
}
成功,code = 200
失敗, code = 404 , msg = Page not found
正在載入中

Java原始碼

判斷的部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static final String checkStatus(@NotNull NetworkEvent status) {
   // 檢查參數是否為null
   Intrinsics.checkNotNullParameter(status, "status");
   // 傳回值
   String var10000;

   // 判斷是不是Load類別
   if (status instanceof NetworkEvent.Load) {
      var10000 = "正在載入中";
   } else if (status instanceof NetworkEvent.Success) { // 判斷是否為Success類別
      var10000 = "成功,code = " + ((NetworkEvent.Success)status).getCode();
   } else {
      // 判斷是否為Error類別
      if (!(status instanceof NetworkEvent.Error)) {
         throw new NoWhenBranchMatchedException();
      }

      var10000 = "失敗, code = " + ((NetworkEvent.Error)status).getErrCode() + " , msg = " + ((NetworkEvent.Error)status).getMsg();
   }
   
   return var10000;
}

main的部分。

1
2
3
4
5
6
7
8
9
10
11
public static final void main() {
   NetworkEvent.Load loading = NetworkEvent.Load.INSTANCE;
   NetworkEvent.Success success = new NetworkEvent.Success(200);
   NetworkEvent.Error error = new NetworkEvent.Error(404, "Page not found");
   String result = checkStatus((NetworkEvent)success);
   System.out.println(result);
   result = checkStatus((NetworkEvent)error);
   System.out.println(result);
   result = checkStatus((NetworkEvent)loading);
   System.out.println(result);
}

results matching ""

    No results matching ""