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

Why do I have to wrap my Kotlin method references in closures?

在 kotlin 中,我正在尝试创建调度 table:

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)

Kotlin 似乎不喜欢这样,它以多种方式抱怨,但相关的似乎是 function invocation expected

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

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

没有别的办法了吗?为什么我必须在相同的闭包中使用正确的方法签名?闭包和方法在 Kotlin 中不是同一个立足点吗?

在没有闭包的情况下,表达式在行中求值(调用)。

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

唯一的例外是当使用 lambda 的函数被声明为 inline 时,在这种情况下整个函数块被注入到调用位置,包括 lambda(以防止生成对象)。

在 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++,由于语言限制,方法和 properties/fields 不能共享相同的名称。在这些语言中,. 适用于方法 groups/function 指针,因为 foo.bar 不可能有歧义。