我想在可空对象上传递函数引用。以 Android 为例,假设我想Activity#onBackPressed从作为该活动的子级的片段中使用。
如果我想调用这个函数,我可以很容易地做到
activity?.onBackPressed()
Run Code Online (Sandbox Code Playgroud)
但是,假设我想将其作为参考传递:
val onBackPressedRef = activity::onBackPressed
Run Code Online (Sandbox Code Playgroud)
这给出了熟悉的空安全错误Only safe or non null asserted calls are allowed...
我可以通过以下方式消除错误,但使用!!显然并不理想:
val onBackPressedRef = activity!!::onBackPressed
Run Code Online (Sandbox Code Playgroud)
尝试activity?::onBackPressed是我的第一直觉,但这也打破了几个错误,解释器似乎很困惑。
val onBackPressedRef = activity?.let { it::onBackPressed }
Run Code Online (Sandbox Code Playgroud)
最后一个变体有效,但它比仅使用?::. 我检查了我能找到的所有文档,但我觉得我错过了一些东西。有任何想法吗?
你是对的,?::Kotlin 中没有运算符。
您有几种选择:
let和run因此,您必须使用辅助函数。代替let(),您还可以使用run(),使表达式更短一点:
val onBackPressedRef = activity?.let { it::onBackPressed }
val onBackPressedRef = activity?.run { ::onBackPressed }
Run Code Online (Sandbox Code Playgroud)
但请记住,无论哪种方式,调用也会更加冗长:
onBackPressedRef?.invoke(args)
Run Code Online (Sandbox Code Playgroud)
因此,您应该问问自己,这是否真的是您想要的,或者是否也可以接受无操作函数调用。
您可以使用闭包——但这会改变语义:
val onBackPressedRef = { activity?.onBackPressed() }
Run Code Online (Sandbox Code Playgroud)
在这里,onBackPressedRef不再可以为空,因此您可以使用()运算符调用它,如果为空activity,它将无效。
如果您经常遇到带有可为空对象的函数引用,您可以编写自己的小抽象:
// Return type: () -> Unit
fun <T> funcRef(obj: T?, function: T.() -> Unit) = { obj?.function() }
Run Code Online (Sandbox Code Playgroud)
这为非空函数变量交换了不同的语法:
// activity can be null
val onBackPressedRef = funcRef(activity, Activity::onBackPressed)
// Callable directly
onBackPressedRef()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |