Котлин - недобросовестное поведение Элвиса - PullRequest
1 голос
/ 10 октября 2019

Столкнулся с интересным случаем, когда Элвис Оператор ?: неправомерно ведет себя.

Представьте себе что-то вроде этого

base64ToBmp(str)?.let { <1> } ?: run { <2> }

и увидите, что на некоторых старых телефонах и эмуляторах вызывается код <1> и <2>.

  • <1> отображало растровое изображение

  • <2> отображало ошибку

Это быловедя себя как Bitmap не удалось разобрать.

Кто-нибудь видел такое поведение? Есть логическое объяснение?

Ответы [ 2 ]

6 голосов
/ 10 октября 2019

let возвращает значение указанного функционального блока.

Таким образом, логическое объяснение состоит в том, что <1> возвращает null. В этом случае все выражение base64ToBmp(str)?.let { <1> } становится null и будет вычисляться правая часть оператора elvis (т.е. run { <2> }).

Очень упрощенный способ его воспроизведения:

"foo"?.let { print("<1>"); null } ?: print("<2>")
// Prints <1><2>

В зависимости от вашего фактического варианта использования может подойти apply или also (которые оба возвращают сам объект контекста) (обратите внимание, что для apply ссылка на объект передается как this вместо it):

"foo"?.apply { print("<1>"); null } ?: print("<2>")
// Prints <1>
2 голосов
/ 10 октября 2019

@ Ответ Марвина правильный, если вы хотите воспроизвести сценарий, вы можете попробовать этот фрагмент кода:

fun main() {
    fun someMethod(param: String?) = param

    fun letBlock(param: String): String? {
        println("<1>")
        return null
    }

    someMethod("some param")?.let(::letBlock) ?: run {
        println("<2>")
    }
}

Вывод:

<1>
<2>
...