考虑用 Java 定义的 SAM
public interface Transform {
public String apply(String str);
}
Run Code Online (Sandbox Code Playgroud)
该接口自动支持 Kotlin 中的 lambda 到类型转换
fun run(transform: Transform) {
println(transform.apply("world"))
}
run { x -> "Hello $x!!" } // runs fine without any issues
Run Code Online (Sandbox Code Playgroud)
但现在考虑一个 Kotlin 接口
interface Transform2 {
fun apply(str: String): String
}
Run Code Online (Sandbox Code Playgroud)
现在调用 run 函数的唯一方法是创建 Transform2 的匿名实例
run(object : Transform2 {
override fun transform(str: String): String = "hello $str!!"
})
Run Code Online (Sandbox Code Playgroud)
但如果我们将 Transform2 接口设为函数式接口,则以下情况是可能的
run { str -> "hello $str!!" }
Run Code Online (Sandbox Code Playgroud)
为什么 Kotlin 编译器无法自动将 lambda 类型转换为匹配的接口(就像处理 Java 接口一样),而不需要显式地将所述接口标记为函数式接口。
Swe*_*per 10
...将所有适用的接口视为 SAM 可能过于意外/隐含:具有 SAM 适用接口的人可能不会假设它将用于 SAM 转换。因此,向接口添加另一个方法变得更加痛苦,因为它可能需要更改调用站点上的语法(例如,将可调用引用转换为对象文字)。
因此,当前的愿景是为接口添加某种修饰符,在应用时:
- 添加接口是否为有效 SAM 的检查
- 允许在调用站点上进行 SAM 转换
像这样的东西:
Run Code Online (Sandbox Code Playgroud)fun interface MyRunnable { fun run() }
基本上,他是说,如果默认情况下隐式完成 SAM 转换,并且我向接口添加一些新方法,则将不再执行 SAM 转换,并且需要更改每个使用转换的地方。“fun”一词的作用是告诉编译器检查该接口确实只有一个抽象方法,同时也告诉调用站点这确实是一个 SAM 接口,他们可以期望作者不会突然添加新的抽象方法方法到接口,突然破坏了他们的代码。
该线程继续讨论为什么相同的论点不能应用于 Java,原因本质上可以归结为“Java 不是 Kotlin”。
| 归档时间: |
|
| 查看次数: |
612 次 |
| 最近记录: |