美文网首页
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