在 lambda 函数中获取接口引用
Getting an interface reference inside a lambda function
考虑以下代码:
val hwnd = Handler()
hwnd.postDelayed(object : Runnable {
override fun run()
hwnd.postDelayed(this, 5000)
}
}, 5000)
这样,我可以在 run()
方法中使用 this
(指的是 Runnable) post 相同的 Runnable 到 Handler。但是我怎么能只使用一个 lambda 表达式来做同样的事情呢?
val hwnd = Handler()
hwnd.postDelayed({
//How to get "this" here?
}, 5000)
这可能吗?
您指的是此处所述的 "qualified this":
这是不可能的。可以参考this discussion:Is the “this” accessible in SAMs?
this
in a lambda refers to the instance of the containing class, if
any. A lambda is conceptually a function, not a class, so there is no
such thing as a lambda instance to which this
could refer.
The fact that a lambda can be converted into an instance of a SAM
interface does not change this. Having this
in a lambda mean different
things depending on whether the lambda gets SAM-converted would be
extremely confusing.
您可以创建一个解决方法(例如讨论中建议的):创建一个扩展函数:
inline fun runnable(crossinline body: Runnable.() -> Unit) = object : Runnable {
override fun run() = body()
}
然后你可以这样称呼它
hwnd.postDelayed(runnable { hwnd.postDelayed(this, 5000) }, 5000)
由于默认的 lambda 转换为您提供带有 () -> Unit
签名的 lambda,这意味着底层 Runnable
是完全隐藏的。
您必须处理手动对象创建,或者编写一个包装器扩展函数来使用具有另一个签名的 lambda:
// custom extension function for handler
inline fun Handler.postDelayed(delayMilis: Long, crossinline runnable: (Runnable) -> Unit) = postDelayed(object : Runnable{
override fun run() {
runnable(this)
}
}, delayMilis)
然后在调用端你会得到 Runnable
对象作为 lambda 参数(只有参数:it
):
hwnd.postDelayed(5000){
// it : Runnable
hwnd.postDelayed(it, 5000)
}
或者如果你真的想变得更花哨,将扩展参数更改为 Handler.(Runnable) -> Unit
,那么你将能够调用:
hwnd.postDelayed(5000){
// this : Handler, it : Runnable
postDelayed(it, 5000)
}
考虑以下代码:
val hwnd = Handler()
hwnd.postDelayed(object : Runnable {
override fun run()
hwnd.postDelayed(this, 5000)
}
}, 5000)
这样,我可以在 run()
方法中使用 this
(指的是 Runnable) post 相同的 Runnable 到 Handler。但是我怎么能只使用一个 lambda 表达式来做同样的事情呢?
val hwnd = Handler()
hwnd.postDelayed({
//How to get "this" here?
}, 5000)
这可能吗?
您指的是此处所述的 "qualified this":
这是不可能的。可以参考this discussion:Is the “this” accessible in SAMs?
this
in a lambda refers to the instance of the containing class, if any. A lambda is conceptually a function, not a class, so there is no such thing as a lambda instance to whichthis
could refer.The fact that a lambda can be converted into an instance of a SAM interface does not change this. Having
this
in a lambda mean different things depending on whether the lambda gets SAM-converted would be extremely confusing.
您可以创建一个解决方法(例如讨论中建议的):创建一个扩展函数:
inline fun runnable(crossinline body: Runnable.() -> Unit) = object : Runnable {
override fun run() = body()
}
然后你可以这样称呼它
hwnd.postDelayed(runnable { hwnd.postDelayed(this, 5000) }, 5000)
由于默认的 lambda 转换为您提供带有 () -> Unit
签名的 lambda,这意味着底层 Runnable
是完全隐藏的。
您必须处理手动对象创建,或者编写一个包装器扩展函数来使用具有另一个签名的 lambda:
// custom extension function for handler
inline fun Handler.postDelayed(delayMilis: Long, crossinline runnable: (Runnable) -> Unit) = postDelayed(object : Runnable{
override fun run() {
runnable(this)
}
}, delayMilis)
然后在调用端你会得到 Runnable
对象作为 lambda 参数(只有参数:it
):
hwnd.postDelayed(5000){
// it : Runnable
hwnd.postDelayed(it, 5000)
}
或者如果你真的想变得更花哨,将扩展参数更改为 Handler.(Runnable) -> Unit
,那么你将能够调用:
hwnd.postDelayed(5000){
// this : Handler, it : Runnable
postDelayed(it, 5000)
}