1 其子类可以出现在定义 sealed class 的不同文件中,但不允许出现在与不同的 module 中,且需要保证 package 一致
2 sealed class 是抽象类,可以拥有抽象方法,无法直接实例化。
3 sealed class 的实例,可配合 when 表达式进行判断,当所有类型覆盖后可以省略 else 分支。如果没有覆盖所有类型,也没有 else 统筹则会发生编译警告或错误
4 当 sealed class 没有指定构造方法或定义任意属性的时候,建议子类定义成单例,因为即便实例化成多个实例,互相之间没有状态的区别
5 子类,包括普通 class、data class、object、sealed class 等
sealed class GameAction(times: Int) {
object Start : GameAction(1)
data class AutoTick(val time: Int) : GameAction(2)
class Exit : GameAction(3)
}
object Restart : GameAction(4)
判断 sealed class 内部子类类型自然需要指定父类前缀
object class 的话可以直接进行实例判断,也可以用 is 关键字判断类型匹配
普通 class 类型的话则必须加上 is 关键字
判断 sealed class 外部子类类型自然无需指定前缀
class TestSealed {
fun test(gameAction: GameAction) {
when (gameAction) {
GameAction.Start -> {}
// is GameAction.Start -> {}
is GameAction.AutoTick -> {}
is GameAction.Exit -> {}
Restart -> {}
}
}
}
enum class Action {
Tick,
// GameAction
Start, Exit, Restart,
// BirdAction
Up, Down, HitGround, HitPipe, CrossedPipe,
// PipeAction
Move, Reset,
// RoadAction
// 防止和 Pipe 的 Action 重名导致编译出错,
// 将功能差不多的 Road 移动和重置 Action 定义加上了前缀
RoadMove, RoadReset
}
fun dispatch(action: Action) {
when (action) {
Action.Tick -> TODO()
Action.Start -> TODO()
Action.Exit -> TODO()
Action.Restart -> TODO()
Action.Up -> TODO()
Action.Down -> TODO()
Action.HitGround -> TODO()
Action.HitPipe -> TODO()
Action.CrossedPipe -> TODO()
Action.Move -> TODO()
Action.Reset -> TODO()
Action.RoadMove -> TODO()
Action.RoadReset -> TODO()
}
}
借助 sealed interface 我们可以给抽出 interface,并将 enum 进行层级拆分。更加清晰、亦不用担心重名
sealed interface Action
enum class GameAction : Action {
Start, Exit, Restart
}
enum class BirdAction : Action {
Up, Down, HitGround, HitPipe, CrossedPipe
}
enum class PipeAction : Action {
Move, Reset
}
enum class RoadAction : Action {
Move, Reset
}
object Tick: Action
使用的时候就可以对抽成的 Action 进行嵌套判断:
fun dispatch(action: Action) {
when (action) {
Tick -> TODO()
is GameAction -> {
when (action) {
GameAction.Start -> TODO()
GameAction.Exit -> TODO()
GameAction.Restart -> TODO()
}
}
is BirdAction -> {
when (action) {
BirdAction.Up -> TODO()
BirdAction.Down -> TODO()
else -> TODO()
}
}
is PipeAction -> {
when (action) {
PipeAction.Move -> TODO()
PipeAction.Reset -> TODO()
}
}
is RoadAction -> {
when (action) {
RoadAction.Move -> TODO()
RoadAction.Reset -> TODO()
}
}
}
}