Kotlin: Как использовать условие типа Else с блокировкой let при проверке на 'null' - PullRequest
3 голосов
/ 10 июля 2019

Я заменяю всю проверку на ноль блоком let в моем коде,

1.Пример кода с проверкой нуля:

if(someValue != null){//run if someValue is not null}
else {//run if someValue is null}

2.Кодовая база после использования блока let-run, если для проверки нуля,

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?.run {
//This code block should run only when if someValue is null, like else condition
}

Теперь проблема с блоком let-run заключается в том, что оба блока кода работают, даже если someValue не равно нулю.Поэтому я не могу реплицировать поведение условия if-else в примере кода 1 на условие run-let в примере кода 2.

Ожидаемое поведение - выполнить блок кода let или run на основе, если значение равно нулюили не-ноль.

Ответы [ 4 ]

5 голосов
/ 10 июля 2019

Я заменяю всю проверку на ноль блоком let в моем коде

Первый вопрос здесь, почему?Это как-то более читабельно для вас, чем обычная структура if-else?Я бы вообще был осторожен с рефакторингом просто ради рефакторинга.

Второе соображение гораздо важнее: это преобразование, которое вы делаете, не эквивалентно исходному коду, вы фактически модифицируете поведение с помощью этогоменять.Возьмем следующий фрагмент кода:

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
    foo(someSafeValue)
    bar(someSafeValue)
} ?: run {
    println("shouldn't happen if someValue != null")
}

Вы ожидаете, что блок run будет выполняться только если someValue == null, но на самом деле это не единственный случай, когда он будет работать.Полное выражение someValue?.let { ... } может выдавать значения null не только тогда, когда сам someValue был null, но также и если блок, переданный в let, возвращал null.В этом случае, если в результате вызова функции bar() получится null, оператор run будет выполнен впоследствии, следовательно, будут выполнены обе ветви того, что вы считали фантастическим оператором if-else.

2 голосов
/ 10 июля 2019

Источник - kotlinlang.org

  • ?.выполняет безопасный вызов (вызывает метод или обращается к свойству, если получатель не равен нулю)
  • ?: принимает правое значение, если левое значение равно нулю (оператор elvis)

Изменение ?. с помощью ?: решит эту проблему,

База кода, как показано ниже, будет запускать блок разрешения или запуска на основепроверка на ноль.

var someValue : String? = null
someValue = "SOF"

someValue?.let {safeSomeValue->
//This code block will run only if someValue is not null
}?:run {
//This code block will run only when if someValue is null, like else condition
}
0 голосов
/ 11 июля 2019

Чтобы дать очень конкретный пример того, о чем говорит ответ zsmb13:

val someValue = 0
someValue?.let { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

печатает как then, так и else.Вы можете исправить это, используя also вместо let:

val someValue = 0
someValue?.also { safeSomeValue->
    println("then")
    null
} ?: run {
    println("else")
}

будет печатать только then.Может быть полезно прочитать https://kotlinlang.org/docs/reference/scope-functions.html и выяснить, почему, и доказать, что это действительно всегда эквивалентно оригиналу if ... else.Но я также согласен с zsmb13, что это, вероятно, плохая идея.

0 голосов
/ 10 июля 2019

Вы можете создать функцию расширения, например:

fun <T> T?.whenNull(block: () -> Unit) = this ?: block()

тогда вы называете это так

somevalue?.let { safeSomeValue ->
    // TODO
}.whenNull {
    // execute when someValue is null
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...