【问题标题】:Function interface in Kotlin 1.4Kotlin 1.4 中的函数接口
【发布时间】:2019-12-22 07:34:22
【问题描述】:

此功能即将推出Kotlin 1.4。这是KotlinConf'19的摘录。

fun interface Action {
    fun run()
}

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

runAction{
    println("Hello")
}

它看起来不错,但我仍然不知道它的作用。

什么是函数接口?它的实用价值是什么?可以用于哪些具体场景?

【问题讨论】:

    标签: kotlin functional-interface


    【解决方案1】:

    这是关于功能接口 — 与单一抽象方法的接口(也称为 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 样式的快捷方式,如您的示例所示。

    (您可能认为这是一件好事,也可能不认为这是一件好事……)

    【讨论】:

    • 这样的函数可以内联吗?
    • @LppEdd 当通过接口调用时不,不 - 因为调用者不知道可能调用哪个实现(动态调度)。 (如果直接调用它可以内联函数——但如果你已经引用了确切的函数或对象,则不需要接口!)另见this question
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 2021-12-19
    相关资源
    最近更新 更多