Skip to content
Advertisement

field initialization with `val myVal: (long: Long) -> Unit)` what does it means?

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 call clickListener(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

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.)

Advertisement