为什么我必须将我的Kotlin方法引用包装在闭包中?

时间:2018-07-13 22:18:21

标签: kotlin closures deferred-execution

在Kotlin中,我正在尝试创建一个调度表:

class Foo {
    fun handleEvent(bytes:ByteArray) {
        // do something fun with the bytes
    }
}

class Bar {
    fun handleEvent(bytes:ByteArray) {
        // do something fun with the bytes
    }
}

foo = Foo()
bar = Bar()

val eventHandlers:HashMap<RemoteEvent, (bytes:ByteArray)->Unit> = hashMapOf(
    0x01 to foo.handleEvent,
    0x02 to bar.handleEvent)

科特林似乎不喜欢这种说法,它有多种抱怨方式,但其中一个似乎是function invocation expected

我可以通过将它们包装在闭包中来解决此问题:

val eventHandlers:HashMap<RemoteEvent, (bytes:ByteArray)->Unit> = hashMapOf(
    0x01 to { bytes -> foo.handleEvent(bytes) },
    0x02 to { bytes -> bar.handleEvent(bytes) })

还有别的办法吗?为什么我必须在相同的闭包中使用正确的方法签名?在Kotlin中,闭包和方法是否处于同一立场?

2 个答案:

答案 0 :(得分:4)

在Kotlin中,函数引用是使用::运算符(不是.)创建的。

使用以下方法可以轻松实现您的预​​期用例:

val eventHandlers: HashMap<RemoteEvent, (bytes: ByteArray) -> Unit> = hashMapOf(
        0x01 to foo::handleEvent,
        0x02 to bar::handleEvent)
                 // ^

Function references,Kotlin文档

foo.handleEvent被解释为访问名为handleEvent(不存在)的属性

foo::handleEvent是一个KFunction实例,表示名为handleEvent的函数,由于它与lambda签名(ByteArray) -> Unit匹配,因此可以正常工作。

请注意,这与例如C#或C ++,由于语言限制,方法和属性/字段不能共享相同的名称。在这些语言中,.适用于方法组/函数指针,因为foo.bar不可能是模棱两可的。

答案 1 :(得分:0)

在没有闭包的情况下,对表达式进行评估(调用)。

闭包生成具有定义方法(在闭包内)的匿名对象,可以在需要时调用该对象。

只有在将使用lambda的函数声明为inline的情况下例外,在这种情况下,整个功能块(包括lambda)都被注入到调用位置(以防止生成对象)。