密封类

密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。

声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。

sealed 不能修饰 interface ,abstract class(会报 warning,但是不会出现编译错误)

密封类一般情况都,都是配合 when 来实用的类,假如有这么一个操作 UI 的类,我们需要操作 UI 的显示和隐藏,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sealed class UIOperator {
    object Show : UIOperator()

    object Hide : UIOperator()
}

fun invoke(view: View ,uiOperator: UIOperator) = when(uiOperator) {
    UIOperator.Show -> view.visibility = View.VISIBLE
    UIOperator.Hide -> view.visibility = View.INVISIBLE
}

这样的代码,其实用枚举也可以做,但是枚举只能有一个实例,假如这里我们后续要添加平移的方法,还需要一些参数的传入,如果用枚举的话,就不太好实现了。这时密封类就发挥优势了。再给 UIOperator 定义两个方法

1
2
3
4
5
6
7
8
9
sealed class UIOperator {

    object Show : UIOperator()

    object Hide : UIOperator()

    class TranslateX(val px: Float): UIOperator()
    class TranslateY(val px: Float): UIOperator()
}

同时使用密封类有一个好处,不需要我们再实现 else 语句的代码,因为密封类已经知道我们要实现哪些方法了,同时如果在密封类中新增加了方法,原来使用到了的地方就需要强制实现新增加的方法了,也就是像下面图片那样,这样就不用凭借记忆那个地方有调用的地方了。

完整代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
sealed class UIOperator {
    object Show : UIOperator()

    object Hide : UIOperator()

    class TranslateX(val px: Float) : UIOperator()
    class TranslateY(val py: Float) : UIOperator()
}

fun invoke(view: View, uiOperator: UIOperator) = when (uiOperator) {
    UIOperator.Show -> view.visibility = View.VISIBLE
    UIOperator.Hide -> view.visibility = View.INVISIBLE
    is UIOperator.TranslateX -> view.translationX = uiOperator.px
    is UIOperator.TranslateY -> view.translationX = uiOperator.py
}