这篇文章上次修改于 1405 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

2020 年 8 月 17 日期待已久的 Kotlin 1.4 正式版终于发布了。

SAM 全称 (Single Abstract Method Conversions) 对只有单个并且是非默认抽象方法的接口转换为 Lambda

在看到 Kotlin 1.4 预览版之前,我一直在迷惑一件事情,就是 Kotlin 对 Java 接口的 SAM 转换。如果以后有些库改成了 Kotlin 那岂不是要炸了。举个例子。

interface OnCallKotlin {
    fun onCall(param: Int)
}
public interface OnCallJava {
    void onCall(int param);
}
fun setOnCallJava(call: OnCallJava) {
    call.onCall(1)
}

fun setOnCallKotlin(call: OnCallKotlin) {
    call.onCall(2)
}

fun main(){
    // 这是正常的 Kotlin 实现接口的写法
    setOnCallJava(object : OnCallJava {
        override fun onCall(param: Int) {
        }
    })

    // Java 的接口如果只有一个方法可以进行简写
    setOnCallJava {}
}

但是 Kotlin 实现的接口并不能这样简写,你想一下这种情况,所有涉及单一方法的接口的地方,如果相关的库从 Java 迁移到 Kotlin 那么你写的代码就全都炸了。我一直为这个事情担心,比较克制的使用简写的方式(如果你不用简写方式编辑器会提示一个警告),直到我看到 Kotlin 1.4 预览版实现了 Kotlin 接口的 SAM 转换,我才敢大胆使用简写方式。

举一个常见的例子,比如 Android 中设置点击事件, setOnClickListener{ } 完全可以使用简写方式,在此之前我非常害怕,如果哪一天 Google 将底层 Library 实现改为 Kotlin 那么全部爆炸。

接下来看一下 Kotlin 1.4 带来的 Kotlin 接口 SAM 转换功能。

fun interface OnCallKotlin {
    fun onCall(param: Int)
}

fun main(){
    // 这是正常的 Kotlin 实现接口的写法
    setOnCallKotlin(object : OnCallKotlin {
        override fun onCall(param: Int) {
        }
    })

    // Kotlin 的接口也可以进行简写
    setOnCallKotlin{}
}

你只需要在 interface 加上 fun 关键字,就可以使用 SAM 转换功能了。