Function Type is an Interface

I read in some articles that under the hood, function types are actually interfaces, can anyone explain to me, what does this mean and how we can use this concept in the real world (need a simple example to understand the concept :pray:)

It’s not something you normally need to know about or use — it’s mostly a detail of how the Kotlin-to-bytecode compiler is implemented. So it’s not worth worrying about.

But if you’re interested in that sort of detail:

Java bytecode doesn’t have a first-class function type. All it has are primitives (integers, characters, booleans, etc.) and references (to objects or to arrays); those are the only values you can store in objects, pass as method parameters, return from methods, etc. So the Kotlin compiler has to convert first-class functions into something the JVM can handle.

So Kotlin’s runtime library defines a series of generic interfaces called Function0, Function1, up to Function22, representing functions that take 0, 1,… 22* parameters. The interfaces all have a single method called invoke(), which implements by the function.

For example, suppose the Kotlin code declares a value of type (Int) -> String — a function that takes a single Int parameter and returns a String. Then the compiled bytecode will have an object of type Function1<Int, String> containing a method invoke(p1: Int): String.

Because that’s an object, it can be assigned and passed around just like other objects. And to call the function, you simply call its invoke() method.

All that is normally hidden from you when you write Kotlin code. But there are a few rare cases when it might ‘leak out’, e.g. in error messages or serialised forms. And you’ll need to use the interfaces if you’re writing Java code that has to interoperate with Kotlin function types.

(* Kotlin does allow functions with more than 22 parameters, but I don’t know how; it must use some other way to implement them.)

2 Likes

Thanks :pray: I understand better now, just to push this forward I’m asking myself this question: Can inheriting a class from a function type be useful as a technique in real-world applications? for example :

class OnClick : (Int) -> Unit {
    override fun invoke(viewId: Int) {
        println("onclick invoked viewID is : $viewId")
    }
}

fun setListener(id : Int, listener: (Int) -> Unit) { /*...*/
    listener(id)
}

fun main() {
  
    val onClick = OnClick()
    setListener(4, onClick)

}
1 Like

Yes, but in such case you can also use a fun interface, which functions like a function type, but allows you more freedom in the naming and subtyping relationships.

2 Likes

Thanks :pray: