In kotlin, I'm trying to create a dispatch 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 doesn't seem to like this, it complains in multiple ways, but the relevant one seems to be be function invocation expected
.
I can fix this by wrapping those in closures:
val eventHandlers:HashMap<RemoteEvent, (bytes:ByteArray)->Unit> = hashMapOf(
0x01 to { bytes -> foo.handleEvent(bytes) },
0x02 to { bytes -> bar.handleEvent(bytes) })
Is there no other way? Why do I have to the method signatures, which are correct, in closures which are the same? Are closures and methods not on the same footing in Kotlin?
In Kotlin, function references are created with the ::
operator (not .
).
Your intended use case can easily be achieved using this:
val eventHandlers: HashMap<RemoteEvent, (bytes: ByteArray) -> Unit> = hashMapOf(
0x01 to foo::handleEvent,
0x02 to bar::handleEvent)
// ^
Function references, Kotlin docs
foo.handleEvent
is interpreted as accessing the property called handleEvent
(which doesn't exist.)
foo::handleEvent
is a KFunction
instance representing the function called handleEvent
, and since this matches the lambda signature (ByteArray) -> Unit
it works as expected.
Notice that this is different from e.g. C# or C++, where due to language restrictions, methods and properties/fields cannot share the same name. In these languages .
is fine for method groups/function pointers because it is impossible that foo.bar
would be ambiguous.