代码之家  ›  专栏  ›  技术社区  ›  J. Doe

如何将“when”与2个密封类一起使用并获取内部值?

  •  1
  • J. Doe  · 技术社区  · 3 年前

    考虑一下这个极端简化的代码(可在 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<人A、 个人。A>期望 '->'应为元素不兼容的类型:Person。A和 配对<人A、 个人。A>

    2 回复  |  直到 3 年前
        1
  •  4
  •   Tenfour04    3 年前

    除了不支持该语法之外(您只能使用 is 关于一件事 when 分支),通过使用 to 您实际上是在创建Pair类的一个实例。

    Pair对其两个变量的类型使用泛型,因此此类型信息在运行时会丢失,原因是 类型消除 .

    所以尽管如此,你 可以 这样做:

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

    只有当两者都 a b 是局部变量,其类型在本地声明,因此Pair的泛型类型在编译时是已知的。但这使它几乎毫无用处,因为如果 b 是在编译时具有已知类型的局部变量,则可以将上面的内容替换为true或false。

    为了能够以通用的方式执行类似的操作,您必须创建要使用的局部变量:

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

    或使用 什么时候 没有主题,并对每个分支设置完整条件:

    when {
        a is Person.A && b is Person.A -> //...
        //...
    }
    
        2
  •  0
  •   Anish Gupta    3 年前

    (a到b)返回一个Pair<人A、 个人。A>但您要检查的是Type Person。A键入人员。A而不是类型对<人A、 个人。A>。

    相反,您可以做的是:

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