hzqelf
hzqelf

Reputation: 907

Function interface in Kotlin 1.4

This feature will be coming Kotlin 1.4. Here is an excerpt from KotlinConf'19.

fun interface Action {
    fun run()
}

fun runAction(a: Action) = a.run()

runAction{
    println("Hello")
}

It looks nice, but I still don't know what it does.

What is the function interface? What is its practical value? What specific scenarios can it be used for?

Upvotes: 12

Views: 6167

Answers (1)

gidds
gidds

Reputation: 18547

This is about functional interfaces — interfaces with a Single Abstract Method (also called SAM interfaces).

To understand the point, I'll need to cover a little history…  In Java, lambdas were added relatively recently.  Before that, you implemented callbacks and similar by implementing a suitable interface.  For example, if you wanted to be informed when an AWT component was actioned, you'd create an object which implemented the ActionListener interface.  That has a single method (called actionPerformed()); you'd put your code inside that method:

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // Do something
    }
});

When they added lambdas, they wanted to blend in with all the existing code, and change as little as possible, so they did it exactly the same way: the compiler infers which interface you're implementing, and creates an object implementing that interface.  You could write:

myButton.addActionListener(e -> {
    // Do something
});

which is shorter — but it compiles down to pretty much the same as the first example.

So in Java, functions are not first-class objects; lambdas are simply a more concise way to implement functional interfaces.

In Kotlin, however, functions are first-class objects: you can write a lambda (or an anonymous function) on its own, assign it, pass it to functions, return it from functions, and so on — so there's no need for SAM interfaces at all!

For easier interoperability with Java, Kotlin lets you easily implement Java SAM interfaces, in the same way you do from Java:

myButton.addActionListener {
    // Do something
}

But Kotlin <= 1.3 doesn't let you implement Kotlin interfaces that way; you need to implement those explicitly.  (I suspect this was partly to encourage developers to use proper functions, with all their other advantages, and not rely on the Java-style workaround.)

Your example illustrates this.  It has an interface (Action) with one abstract method (run()).  It has a function (runAction()) which takes an instance of that interface.  And it has some code which wants to call that function, passing just the code for the run() method.

In Kotlin <= 1.3, you'd have to do the latter explicitly, e.g.:

runAction(object : Action {
    override fun run() {
        println("Hello")
    }
})

But from Kotlin 1.4, you can mark the interface as fun interface, and use the Java-style shortcut, as in your example.

(You may or may not think this is a good thing…)

Upvotes: 31

Related Questions