kotlin 如何使用'when'与2个密封类并获取内部值?

up9lanfz  于 2023-02-24  发布在  Kotlin
关注(0)|答案(2)|浏览(142)

请看下面这个极度简化的代码(https://pl.kotl.in/bb2Irv8dD上提供):

sealed class Person {
    data class A(val i: Int) :
        Person()
}

fun main() {
    val a = Person.A(i = 0)
    val b = Person.A(i = 1)
    
    // Compiles
    when (a) { 
        is Person.A -> print("I have access to {$a.i}")
    }
    
    // Does not compile :(
    when (a to b) { 
        is Person.A to is Person.A -> print("I have access to {$a.i} and b {$b.i}")
    }
}

为什么(a to b)代码不起作用?它只对1个变量起作用,我希望我能在两个类上匹配并得到两个内部值。
错误为:
不兼容的类型:Person.A和Pair〈Person.A,Person.A〉应为"-〉"应为元素不兼容的类型:人员A和配对〈人员A,人员A〉

vuv7lop3

vuv7lop31#

除了不支持该语法(您只能在when分支中的一个对象上使用is)之外,通过使用to,您实际上是在创建Pair类的一个示例。
Pair使用泛型来表示它的两个变量的类型,所以这个类型信息在运行时由于 type erasure 而丢失。
因此,尽管如此,您 * 可以 * 这样做:

when (a to b) { 
    is Pair<Person.A, Person.A> -> print("I have access to {$a.i} and b {$b.i}")
}

只有当ab都是局部变量,并且类型是在本地声明的,所以Pair的泛型类型在编译时是已知的,这使得它几乎毫无用处,因为如果ab是局部变量,并且在编译时类型是已知的,那么你可以用true或false替换上面的值。
为了能够以一般方式执行类似的操作,您必须创建要使用的局部变量:

val aIsTypeA = a is Person.A
val bIsTypeA = b is Person.A
when (aIsTypeA to bIsTypeA) {
    true to true -> //...
    //...
}

或者使用不带主语的when,并在每个分支上放置完整条件:

when {
    a is Person.A && b is Person.A -> //...
    //...
}
ctehm74n

ctehm74n2#

(a to B)返回一个对〈Person.A,Person.A〉,但您检查的是类型Person.A到类型Person.A,而不是类型对〈Person.A,Person.A〉。
你可以做的是:

when (a to b) { 
    is Pair<Person.A,Person.A> -> print("I have access to {$a.i} and b {$b.i}")
}

相关问题