Ошибка компиляции команды с закрытыми классами
С закрытыми классами вы можете использовать исчерпывающие выражения when
и опустить предложение else
, когда выражение возвращает результат:
sealed class SealedClass {
class First : SealedClass()
class Second : SealedClass()
}
fun test(sealedClass: SealedClass) : String =
when (sealedClass) {
is SealedClass.First -> "First"
is SealedClass.Second -> "Second"
}
Теперь, если бы я должен был добавить Third
в SealedClass
, компилятор будет жаловаться, что выражение when
в test()
не является исчерпывающим, и мне нужно добавить предложение для Third
или else
.
Мне интересно, однако, если эта проверка также может быть применена, когда test()
ничего не возвращает:
fun test(sealedClass: SealedClass) {
when (sealedClass) {
is SealedClass.First -> doSomething()
is SealedClass.Second -> doSomethingElse()
}
}
Этот фрагмент не прерывается, если добавлен Third
.
Я могу добавить инструкцию return
до when
, но это можно легко забыть и может сломаться, если тип возврата одного из предложений не Unit
.
Как я могу убедиться, что не забудьте добавить ветвь в мои предложения when
?
Ответы
Ответ 1
Вдохновение от ответа Воддана, вы можете создать свойство под названием safe
, которое вы можете использовать:
val Any?.safe get() = Unit
Для использования:
when (sealedClass) {
is SealedClass.First -> doSomething()
is SealedClass.Second -> doSomethingElse()
}.safe
Я думаю, что это дает более четкое сообщение, чем просто добавление .let{}
или присвоение результата значению.
В трекерах Kotlin есть открытая проблема, которая считает, что поддерживает "запечатанное время".
Ответ 2
Способ принудительного выполнения исчерпывающего when
заключается в том, чтобы сделать его выражением, используя его значение:
sealed class SealedClass {
class First : SealedClass()
class Second : SealedClass()
class Third : SealedClass()
}
fun test(sealedClass: SealedClass) {
val x = when (sealedClass) {
is SealedClass.First -> doSomething()
is SealedClass.Second -> doSomethingElse()
} // ERROR here
// or
when (sealedClass) {
is SealedClass.First -> doSomething()
is SealedClass.Second -> doSomethingElse()
}.let {} // ERROR here
}