Рассмотрим этот предельно упрощенный код (доступен на 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> Ожидание '->' Ожидается элемент Несовместимые типы: Person.A и Пара<Person.A, Person.A>
(a to b) возвращает Pair<Person.A,Person.A>, но вы проверяете Type Person.A на Type Person.A вместо Type Pair<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}")
}
Помимо того, что этот синтаксис не поддерживается (вы можете использовать is
только для одной вещи в ветке when
), с помощью to
вы буквально создаете экземпляр класса 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 известны во время компиляции. Но это делает его в основном бесполезным, потому что если a
и b
являются локальными переменными с известным типом во время компиляции, то вы можете просто заменить вышеуказанное на 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 -> //...
//...
}