科特林? vs ?.let {}

时间:2021-07-31 17:54:28

标签: kotlin

考虑一下我想使用的这个不错的实用程序扩展功能:

<section class="welcome">
  <div class="inner">
    <div class="content">
      <p>Hello Woorld</p>
    </div>
  </div>
</section>

当表达式计算为 null 时,它对于记录内容可能非常有用,例如:

inline infix fun <T> T?.otherwise(other: () -> Unit): T? {
    if (this != null) return this
    other()
    return null
}

但我发现它不适用于:

val x: Any? = null
x?.let { doSomeStuff() } otherwise {Log.d(TAG,"Otherwise happened")}

参见here运行示例

好吧,当我考虑它时,我想这是有道理的,如果 val x: Any? = null x?.otherwise {Log.d(TAG,"Otherwise happened")} 为空,则 x 会使后缀不被执行,但我不明白为什么第一个示例中的 ?有什么不同吗?

是否可以将实用程序修复为更健壮和工作,而无需在链中使用 let

3 个答案:

答案 0 :(得分:3)

首先,您可以简化实现:

inline infix fun <T> T?.otherwise(other: () -> Unit): T? {
    if (this == null) { other() }
    return this
}

inline infix fun <T> T?.otherwise(other: () -> Unit): T? =
    also { if (it == null) other() }

当你这样做时:

null?.otherwise { println("Otherwise happened") }

?. 表示“如果不为空则执行”,因此不执行 otherwise

你需要写的是:

null otherwise { println("Otherwise happened") }

请注意,这与 ?: 运算符非常相似(正如 Vadik 在评论中指出的那样):

null ?: println("Otherwise happened")

区别在于otherwise总是返回左边的值(与also相同),但是当左边的值为null时?:返回右边的值.

在我看来,otherwise 令人困惑,特别是因为它总是返回左值,而不管名称如何。您最好使用 ?: 运算符。或者将其重命名为 alsoIfNull 之类的名称。

答案 1 :(得分:2)

执行 let 示例是因为,当您不使用中缀功能时,它看起来像这样:

x?.let {}.otherwise {println("1")}

注意它不是?.otherwise;因此,它总是执行。

因此要使用不带 otherwiselet,您可以省略 ?

x.otherwise { ... }

答案 2 :(得分:0)


x?.let { doSomeStuff() }.otherwise {Log.d(TAG,"Otherwise happened")}
// ⬇️
val value = if (x != null) {
    doSomeStuff()
} else {
    null
}
value.otherwise {Log.d(TAG,"Otherwise happened")}
x?.otherwise { Log.d(TAG,"Otherwise happened") }
// ⬇️
if (x != null) {
    otherwise { Log.d(TAG,"Otherwise happened") }
} else {
    null
}

?. 表示如果值不为空则执行方法并返回结果,否则返回空