考虑一下我想使用的这个不错的实用程序扩展函数:
inline infix fun <T> T?.otherwise(other: () -> Unit): T? {
if (this != null) return this
other()
return null
}
当表达式求值为null时,它可能非常有用,例如:
val x: Any? = null
x?.let { doSomeStuff() } otherwise {Log.d(TAG,"Otherwise happened")}
,但我看到它不工作:
val x: Any? = null
x?.otherwise {Log.d(TAG,"Otherwise happened")}
查看这里的运行示例
嗯,当思考它的时候,我想这是有意义的,如果x
是空的?
使后缀不被执行,但我不明白为什么let
在第一个例子是不同的?
是否有可能修复实用程序更强大和工作,而不必在链中有let
?
首先,可以简化实现:
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
相同),但?:
在左边的值为空时返回右边的值。
在我看来,otherwise
是令人困惑的,特别是因为它总是返回左值,尽管名称。您最好使用?:
运算符。或者将其重命名为alsoIfNull
。
let
示例执行是因为,当您不使用中缀特性时,它看起来像这样:
x?.let {}.otherwise {println("1")}
注意它不是?.otherwise
;因此,它总是执行。
因此,要使用otherwise
而不使用let
,您可以省略?
。
x.otherwise { ... }
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
}
?.
表示如果值不为空,则执行该方法并返回结果,否则返回null