Reputation: 907
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
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