密封类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种),编译期会有提示,也是很友好的。
以上分析有不对的地方,请指出,互相学习,谢谢哦!
网友评论