Подтвердить что ты не робот

Ошибка компиляции команды с закрытыми классами

С закрытыми классами вы можете использовать исчерпывающие выражения 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?

4b9b3361

Ответ 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
}