在 Kotlin 中,是否可以定义枚举的子集?
enum class Shape {
FULL_HEIGHT_WALL, HALF_HEIGHT_WALL, FULL_HEIGHT_CORNER, HALF_HEIGHT_CORNER, SOMETHING_ELSE
}
fun Shape.isFullHeight() = when (this) {
Shape.FULL_HEIGHT_WALL -> true
Shape.FULL_HEIGHT_CORNER -> true
else -> false
}
fun Shape.isHalfHeight() = when (this) {
Shape.HALF_HEIGHT_WALL -> true
Shape.HALF_HEIGHT_CORNER -> true
else -> false
}
fun test(s: Shape) = when {
s.isFullHeight() -> 1.0f
s.isHalfHeight() -> 0.5f
s == Shape.SOMETHING_ELSE -> 0.42f
// else?!
}
函数
isFullHeight
对于 Shape
的一个子集成立,函数 isHalfHeight
对于另一个子集成立。 test
函数的when语句应该是详尽的;但由于 Kotlin 不明白检查后不会保留任何枚举项,因此它需要一个 else 情况。这有点不幸,因为如果我添加一个 else 情况,如果我添加另一个形状并忘记更新
test
函数,编译器不会抱怨。
那么,是否可以重写此代码,以便 Kotlin 理解我正在检查子集?如果没有,这是否在路线图上? (我认为 TypeScript 能够做到这一点。)
您可以创建一个额外的
Height
枚举。然后您可以使用 Height?
来表示全部、一半或“其他”(null
)。
enum class Height {
FULL, HALF
}
enum class Shape {
FULL_HEIGHT_WALL, HALF_HEIGHT_WALL, FULL_HEIGHT_CORNER, HALF_HEIGHT_CORNER, SOMETHING_ELSE
}
val Shape.height get() = when (this) {
Shape.FULL_HEIGHT_WALL -> Height.FULL
Shape.FULL_HEIGHT_CORNER -> Height.FULL
Shape.HALF_HEIGHT_WALL -> Height.HALF
Shape.HALF_HEIGHT_CORNER -> Height.HALF
else -> null
}
fun test(s: Shape) = when(s.height) {
Height.FULL -> 1.0f
Height.HALF -> 0.5f
null -> 0.42f
}
另一种方法是使用密封类型层次结构。通过实现接口来表示每个案例的高度,并使用
is
中的when
来检查类型。
sealed interface Shape {
object FullHeightWall: FullHeight
object HalfHeightWall: HalfHeight
object FullHeightCorner: FullHeight
object HalfHeightCorner: HalfHeight
object SomethingElse: Shape
}
sealed interface FullHeight: Shape
sealed interface HalfHeight: Shape
fun test(s: Shape) = when(s) {
is FullHeight -> 1.0f
is HalfHeight -> 0.5f
Shape.SomethingElse -> 0.42f
}