考虑一下我想使用的这个不错的实用程序扩展功能:
<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
?
答案 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
;因此,它总是执行。
因此要使用不带 otherwise
的 let
,您可以省略 ?
。
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
}
?.
表示如果值不为空则执行方法并返回结果,否则返回空