考虑一个用 Java 定义的 SAM
public interface Transform {
public String apply(String str);
}
此接口(interface)自动支持 Kotlin 中的 lambda 到类型转换
fun run(transform: Transform) {
println(transform.apply("world"))
}
run { x -> "Hello $x!!" } // runs fine without any issues
但现在考虑一个 Kotlin 接口(interface)
interface Transform2 {
fun apply(str: String): String
}
现在调用 run 函数的唯一方法是创建 Transform2 的匿名实例
run(object : Transform2 {
override fun transform(str: String): String = "hello $str!!"
})
但如果我们将 Transform2 接口(interface)设为函数式接口(interface),则以下是可能的
run { str -> "hello $str!!" }
为什么 Kotlin 编译器不能自动将转换 lambda 类型转换为匹配的接口(interface)(就像它对 Java 接口(interface)所做的那样),而无需将所述接口(interface)显式标记为函数式接口(interface)。
最佳答案
我在 comment 中找到了某种理由。在 KT-7770 :
... treating all the applicable interfaces as SAM might be too unexpected/implicit: one having a SAM-applicable interface may not assume that it will be used for SAM-conversions. Thus, adding another method to the interface becomes more painful since it might require changing syntax on the call sites (e.g. transforming callable reference to object literal).
Because of it, current vision is adding some kind of modifier for interfaces that when being applied:
- Adds a check that the interface is a valid SAM
- Allows SAM-conversions on call sites for it
Something like this:
fun interface MyRunnable { fun run() }
基本上,他的意思是,如果默认情况下隐式完成 SAM 转换,并且我在接口(interface)中添加了一些新方法,则将不再执行 SAM 转换,并且每个使用转换的地方都需要更改。 “有趣”这个词是告诉编译器检查接口(interface)确实只有一个抽象方法,也告诉调用站点这确实是一个SAM接口(interface),他们可以期待作者不要突然添加新的抽象接口(interface)的方法,突然破坏了他们的代码。
线程继续讨论why can't the same argument can't be applied to Java ,以及 reason本质上归结为“Java 不是 Kotlin”。
关于kotlin - 为什么我们需要在 Kotlin 中显式的函数接口(interface)修饰符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70569535/