首页 > 解决方案 > Kotlin 函数引用是否有一个简单的空安全运算符?

问题描述

我想在可空对象上传递函数引用。以 Android 为例,假设我想使用Activity#onBackPressed该活动的子片段。

如果我想调用这个函数,我可以很容易地做到

activity?.onBackPressed()

但是,假设我想将其作为参考传递:

val onBackPressedRef = activity::onBackPressed

这给出了只允许安全或非空断言调用的熟悉的空安全错误......


我可以通过以下方式消除错误,但使用!!显然并不理想:

val onBackPressedRef = activity!!::onBackPressed

尝试activity?::onBackPressed是我的第一直觉,但这也因几个错误而中断,口译员似乎感到困惑。

val onBackPressedRef = activity?.let { it::onBackPressed } 

最后一个变体有效,但它比仅使用?::. 我检查了所有我能找到的文档,但我觉得我错过了一些东西。有任何想法吗?

标签: kotlin

解决方案


?::你是对的, Kotlin中没有运算符。
您有几种选择:

1.letrun

因此,您必须使用辅助函数。代替let(),您也可以使用run(),使表达式稍微短一点:

val onBackPressedRef = activity?.let { it::onBackPressed }
val onBackPressedRef = activity?.run { ::onBackPressed }

但请记住,无论哪种方式,调用都会更加冗长:

onBackPressedRef?.invoke(args)

因此,您应该问自己,这是否真的是您想要的,或者无操作函数调用是否也可以接受。

2. 闭包

您可以使用闭包——但这会改变语义:

val onBackPressedRef = { activity?.onBackPressed() }

在这里,onBackPressedRef不再可以为空,因此您可以使用()运算符调用它,如果为空activity,它将不起作用。

3.助手功能

如果您经常遇到带有可空对象的函数引用,您可以编写自己的小抽象:

// Return type: () -> Unit
fun <T> funcRef(obj: T?, function: T.() -> Unit) = { obj?.function() }

这为非空函数变量交换了不同的语法:

 // activity can be null
 val onBackPressedRef = funcRef(activity, Activity::onBackPressed)

 // Callable directly
 onBackPressedRef()

推荐阅读