0

我有一个密封的类层次结构,如下所示:

sealed class Base

class A : Base()

abstract class B : Base()

class C : Base()
class D : Base()

然后我想要一个详尽的when

fun main() {
    val c: Base = C()
    
    when (c) {
        is A -> println("A")
        is C -> println("C")
        is D -> println("D")
    }.let {}
}

但这是不允许的,因为

'when' expression must be exhaustive, add necessary 'is B' branch or 'else' branch instead

但这不是真的!我已经涵盖了所有可能性。没有任何价值与我的时间不匹配。

此外,如果我添加一个is C子句:

when (c) {
    is A -> println("A")
    is B -> println("B")
    is C -> println("C")
    is D -> println("D")
}.let {}

它实际上没有被称为. C被打印。

这实际上也是另一个方向的问题。假设我想要相同的逻辑来处理B:CD:的所有子类

when (c) {
    is A -> println("A")
    is B -> println("some subclass of B")
}.let {}

这也是不允许的,即使它详尽的。这里发生了什么?这是 Kotlin 中的错误吗?我错过了什么吗?

4

1 回答 1

0

假设您的意思是 C 和 D 是 B 而不是 Base 的子类,那么这种行为是预期的。编译器识别详尽 when 语句的能力仅扩展到密封类的直接子级。C 和 D 不是密封类合同的一部分。如果 C 和 D 扩展 B,这适用于您现有的类设置:

when (c) {
    is A -> println("A")
    is B -> println("B")
}.let {}

如果您将 B 设置为密封类,就像 A 一样,您的原始代码可以工作,编译器可以识别出它是详尽无遗的,而无需在 when 语句中包含 B。

于 2021-01-27T01:43:30.807 回答