I’m new to using Kotlin, so far seems amazing, however I don’t quite understand what’s going on here:
class MyCallbackListener(val clickListener: (myLong: Long) -> Unit){ fun onClick(myObject: MyObjectClass) = clickListener(myObject.longField) }
So, here’s what I do understand:
I am creating a class that contains a method which receives a
MyObjectClass
When I call
onClick(someObject)
I am actually indicating to callclickListener(someObject.longField)
I should use this callback method like this:
MyCallbackListener{ myLong -> //Do Something with mylong, which will be myObject.longField }
Unit is a Kotlin type vaguely like void
However, I don’t really understand the val clickListener: (myLong: Long) -> Unit
part.
It looks like I am declaring a final field for the class which will be of type (myLong: Long) -> Unit
but that does not make a lot of sense.
Why or how is this enabling me to pass in the lambda for the listener?
What’s exactly going on here?
I come from a Java background so it could help if you could provide equivalent code, but that is not strictly necessary
Advertisement
Answer
What you’re looking at is a function type.
(myLong: Long) -> Unit
is the type of a function that takes a single Long parameter, and returns nothing useful. — In fact, the myLong
parameter name is irrelevant here; it could be written more simply as (Long) -> Unit
.
(Yes, Kotlin’s Unit
type is roughly equivalent to Java’s void
: it’s what functions return if they don’t have anything useful to return. That’s not to be confused with Nothing
, which is the return type for functions that never return at all, e.g. because they have an infinite loop or always throw an exception.)
So the caller has to provide a function for that parameter. You’d typically give a lambda, e.g.:
MyCallbackListener({ myLong -> println(myLong) })
(Note that that could be written more simply as MyCallbackListener(){ println(it) }
, since if the last parameter is a lamdba it can be passed outside the brackets, and it
is a keyword which can be used for the single parameter of a lambda.)
But you could instead give a function reference, e.g.:
MyCallbackListener(SomeClass::printLong)
Or an anonymous function, e.g.:
MyCallbackListener(fun(myLong: Long) { println(myLong) })
Or even an instance of an object implementing that function.
This doesn’t have an exact equivalent in Java, because Java doesn’t have first-class functions; it simply implements lambdas as instances of a functional interface (one with a Single Abstract Method) that the compiler infers. (First-class functions are more powerful and more general, though this example doesn’t really demonstrate that.)