kotlin - Kotlin 1.4 中的函数接口
问题描述
此功能即将推出Kotlin 1.4
。这里是摘录自KotlinConf'19
。
fun interface Action {
fun run()
}
fun runAction(a: Action) = a.run()
runAction{
println("Hello")
}
它看起来不错,但我仍然不知道它的作用。
什么是功能接口?它的实用价值是什么?它可以用于哪些具体场景?
解决方案
这是关于功能接口——与单一抽象方法的接口(也称为 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 <= 1.3 不允许您以这种方式实现 Kotlin 接口;你需要明确地实现这些。(我怀疑这部分是为了鼓励开发人员使用正确的函数,以及它们的所有其他优点,而不是依赖于 Java 风格的解决方法。)
您的示例说明了这一点。它有一个接口(Action
)和一个抽象方法(run()
)。它有一个函数 ( runAction()
),它接受该接口的一个实例。它有一些想要调用该函数的代码,只传递该run()
方法的代码。
在 Kotlin <= 1.3 中,您必须明确地执行后者,例如:
runAction(object : Action {
override fun run() {
println("Hello")
}
})
但是从 Kotlin 1.4 开始,您可以将接口标记为fun interface
,并使用 Java 样式的快捷方式,如您的示例所示。
(您可能认为或可能不认为这是一件好事……)
推荐阅读
- python - 不要为我的 GAN 实现获得完整的 GPU 利用率
- python - 正确语法的 Mysql 8.0 语法错误检查手册
- ios - 自定义 URL 方案错误:此应用不允许查询方案
- java - 如何更改不同类的字段值?
- python - TypeError:不可散列的类型:'slice',wh
- android - 使用 Canvas 绘制镂空文字/凹凸效果
- powershell - ADSI 根据 primarygroupid 搜索主组的 DistinguishedName
- odbc - ODBC 为什么平台是 32/64
- import - __import__() 适用于 python3.6.5 但不适用于 python3.7.3
- linux - Laravel 没有从 env 文件中获取默认的 DB_CONNECTION 值