这是关于功能接口 — 与单一抽象方法的接口(也称为 SAM 接口)。
为了理解这一点,我需要介绍一些历史……在 Java 中,lambda 是最近才添加的。在此之前,您通过实现合适的接口来实现回调和类似的。例如,如果您想在 AWT 组件被操作时得到通知,您将创建一个实现 ActionListener 接口的对象。那只有一个方法(称为actionPerformed());您可以将代码放入该方法中:
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Do something
}
});
当他们添加 lambda 时,他们希望与所有现有代码融为一体,并尽可能少地进行更改,因此他们的做法完全相同:编译器会推断您正在实现哪个接口,并创建一个对象来实现那个界面。你可以写:
myButton.addActionListener(e -> {
// Do something
});
它更短——但它的编译结果与第一个示例几乎相同。
所以在 Java 中,函数不是一等的对象; lambda 只是实现功能接口的一种更简洁的方式。
然而,在 Kotlin 中,函数是一等对象:你可以自己编写一个 lambda(或匿名函数),分配它,将它传递给函数,从函数返回它,等等——所以根本不需要 SAM 接口!
为了更轻松地与 Java 进行互操作,Kotlin 可让您轻松实现 Java SAM 接口,就像在 Java 中一样:
myButton.addActionListener {
// Do something
}
但是 Kotlin
您的示例说明了这一点。它有一个接口 (Action) 和一个抽象方法 (run())。它有一个函数 (runAction()),它接受该接口的一个实例。它有一些代码想要调用该函数,只传递run() 方法的代码。
在 Kotlin
runAction(object : Action {
override fun run() {
println("Hello")
}
})
但从 Kotlin 1.4 开始,您可以将接口标记为 fun interface,并使用 Java 样式的快捷方式,如您的示例所示。
(您可能认为这是一件好事,也可能不认为这是一件好事……)