美文网首页
Kotlin-密封类sealed与枚举区别

Kotlin-密封类sealed与枚举区别

作者: 杨0612 | 来源:发表于2021-06-29 14:02 被阅读0次
    密封类sealed例子

    Human模型数据结构,Man、Woman分别是子类。

    name、age是Human共有的属性,a1、a2是Man特有的属性,而a3、a4则是Woman特有的。

    sealed class Human(val name: String, val age: Int) {
        class Man(name: String, age: Int, val a1: Int, val a2: Int) : Human(name, age)
        class Woman(name: String, age: Int, val a3: Int, val a4: Int) : Human(name, age)
    }
    
        //处理
        fun handleHuman(human: Human) {
            when (human) {
                is Human.Man -> {
                    //type 为man的处理
                    Log.d("test",human.a1.toString() + human.a2.toString())
                }
                is Human.Woman -> {
                    //type 为woman的处理
                    Log.d("test",human.a3.toString() + human.a3.toString())
                }
            }
        }
    
    • 从上述可以看出,密封类适合用在父类定义共同属性,子类具有特殊属性的场景,这点跟枚举不一样;
    • 密封类以及它的子类最好都定义在同一个文件中,这样会更加内聚。
    枚举例子

    Human数据结构,枚举Sex是Human中属性。

    class Human(val name: String, val age: Int, var sex: Sex) {
        enum class Sex {
            Man, Woman
        }
    }
        //处理
        fun handleHuman(human: Human) {
            when (human.sex) {
                Human.Sex.Man -> {
                    //sex 为man的处理
                }
                Human.Sex.Woman -> {
                    //sex 为woman的处理
                }
            }
        }
    
    • 上述例子可以看出,枚举一般是跟实体搭配使用的,是实例中的属性。
    网络请求处理案例

    网络请求处理也很适合使用密封类sealed,以下定义网络请求结果Result,ResultSuccess、ResultFailed都是它的子类。handleResult函数判断result的类型做相应的处理。

    sealed class Result
    data class ResultSuccess(val data: String) : Result()
    data class ResultFailed(val failedMsg: String, val failedCode: Int) : Result()
    
     fun handleResult(result: Result) {
            when (result) {
                is ResultSuccess -> {
                    //做网络请求成功处理
                    Log.d("test",result.data)
                }
                is ResultFailed -> {
                    //做网络失败处理
                    Log.d("test",result.failedMsg +result.failedCode.toString() )
                }
            }
        }
    
    • 将上述密封类反编译看下
    public abstract static class Result {
       private Result() {//1
       }
    
       // $FF: synthetic method
       public Result(DefaultConstructorMarker $constructor_marker) {
          this();
       }
    }
    
    public final class ResultSuccess extends Result {
       @NotNull
       private final String data;
    
       @NotNull
       public final String getData() {//1
          return this.data;
       }
    
       public ResultSuccess(@NotNull String data) {
          Intrinsics.checkNotNullParameter(data, "data");
          super((DefaultConstructorMarker)null);
          this.data = data;
       }
    
       @NotNull
       public final String component1() {
          return this.data;
       }
    
       @NotNull
       public final ResultSuccess copy(@NotNull String data) {//2
          Intrinsics.checkNotNullParameter(data, "data");
          return new ResultSuccess(data);
       }
    
       // $FF: synthetic method
       public static ResultSuccess copy$default(ResultSuccess var0, String var1, int var2, Object var3) {
          if ((var2 & 1) != 0) {
             var1 = var0.data;
          }
    
          return var0.copy(var1);
       }
    
       @NotNull
       public String toString() {//3
          return "ResultSuccess(data=" + this.data + ")";
       }
    
       public int hashCode() {//4
          String var10000 = this.data;
          return var10000 != null ? var10000.hashCode() : 0;
       }
    
       public boolean equals(@Nullable Object var1) {//5
          if (this != var1) {
             if (var1 instanceof ResultSuccess) {
                ResultSuccess var2 = (ResultSuccess)var1;
                if (Intrinsics.areEqual(this.data, var2.data)) {
                   return true;
                }
             }
    
             return false;
          } else {
             return true;
          }
       }
    }
    
    • 注释1:增加get函数,跟普通类一致;
    • 注释2:密封类无法实例化,只有它的子类可以
    • 注释3、4、5:增加了toString、hashCode、equals,这都是普通类没有的;
    总结
    • 对比枚举,密封类sealed算是枚举的增强,在可以用来区分类型的基础上,子类可拥有特殊的属性;
    • 对比普通类,密封类sealed自动生成toString、hashCode、equals函数;
    • 密封类,主构造函数的属性不能重写get、set函数;
    • 当密封类sealed用于类型判断,when少了对应的类型处理(定义了3种,只处理了2种),编译期会有提示,也是很友好的。

    以上分析有不对的地方,请指出,互相学习,谢谢哦!

    相关文章

      网友评论

          本文标题:Kotlin-密封类sealed与枚举区别

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