1.3 发了,说两句关于 Kotlin SAM 的

本文探讨了Kotlin SAM特性的发展,从1.3版本的跳票到当前的实验性支持。介绍了Kotlin如何支持Java SAM接口,并展示了Kotlin函数SAM转换的示例。同时,讨论了Kotlin接口的SAM支持面临的挑战和官方的考虑。文章最后展望了未来Kotlin类型系统可能的增强,包括在1.4版本中对Kotlin接口SAM的支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.3 RC 刚出来的时候,有人就不乐意了:说好的 Kotlin 的 SAM 呢?这个曾经存在于 1.3 的谣言当中的特性最终没有被加入到这个版本当中,群里有不少小伙伴表示:失望,哼。

何为 SAM

我们先来简单回顾下何为 SAM。它其实不是英文名 Sam,而是 Single Abstract Method,直接理解就是一个抽象的方法。Kotlin 很早就支持了对 参数包含只有一个方法的 Java 接口的 Java 方法的 SAM 转换,说起来有点儿拗口,我们看个例子:

 
 
  1. public interface Runnable {

  2.    public abstract void run();

  3. }

Runnable 是一个只有一个方法的 Java 接口,我们这时候还有这样的方法:

 
 
  1. void execute(Runnable command){

  2.    ...

  3. }

我们注意到 execute 方法有一个参数是 Runnable,那么在 Kotlin 当中使用 execute 时:

 
 
  1. execute {

  2.    ...

  3. }

Kotlin 允许给 execute 方法传入一个 Lambda 表达式,而不需要 Runnable 的实例,因为在 Kotlin 看来,这个方法它本身是可以接受两种类型的参数的: Runnable()->Unit

那么前面任何一个条件不符合,这个结果就不成立,例如如果 Runnable 是一个 Kotlin 类,或者 execute 是一个 Kotlin 方法,都不可以。

Kotlin 1.3 跳票的 Kotlin SAM 现在怎么样了

虽然 Kotlin 1.3 没有正式把对 Kotlin 的 SAM 丢出来,但确实他们已经在做这件事儿了:NewInference 和 SamConversionForKotlinFunctions ,也就是新的类型推断和对 Kotlin 函数的 SAM 转换 —— 后者依赖于前者。

我们直接看效果,同样对于前面的 Runnable,我们在 Kotlin 当中定义一个函数:

 
 
  1. fun foo(runnable: Runnable){

  2.    ...

  3. }

按照之前的写法,我们只能使用 Runnable 实例传参,现在呢?

 
 
  1. foo {

  2.    println("Hello")

  3. }

有了前面提到的两样,这个就合法了。当然如果你想要亲自体验一下,请在你的 gradle 当中配置:

 
 
  1. compileKotlin {

  2.    kotlinOptions {

  3.        freeCompilerArgs = ["-XXLanguage:+NewInference", "-XXLanguage:+SamConversionForKotlinFunctions"]

  4.    }

  5. }

hmmm,这个给人的感觉一点儿都不好,连 Experimental 都算不上的东西,小伙伴们怎么敢用呢?所以线上的代码大家可以保守一点。当然这也问题不大,毕竟大部分团队可能连 1.3 都来不及切换,何况这些隐藏特性呢。

不过大家也不要觉得这很遥远,因为 Gradle Kotlin DSL 的脚本本身就强开了这俩特性:

 
 
  1. @ScriptTemplateAdditionalCompilerArguments([

  2.    "-jvm-target", "1.8",

  3.    "-Xjsr305=strict",

  4.    "-XXLanguage:+NewInference",

  5.    "-XXLanguage:+SamConversionForKotlinFunctions"

  6. ])

  7. @SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")

  8. abstract class KotlinInitScript(

  9.    private val host: KotlinScriptHost<Gradle>

  10. ) : InitScriptApi(host.target) {

  11.    ...

  12. }

Kotlin 接口呢

尽管有些不太正规,但我们好歹体验了一把 Kotlin 函数的 SAM。问题是,这里定义的接口,仍然需要是 Java 接口,那么 Kotlin 接口呢?

答案是:还不行。

关于这个问题的讨论,可以参见 YouTrack 的讨论:SAM for Kotlin classes [https://youtrack.jetbrains.com/issue/KT-7770],大家可以看到这个问题的讨论从 Kotlin 1.0 之前就开始了,官方的顾虑主要是一旦引入了对 Kotlin 接口的 SAM,会对整个 Kotlin 的类型系统引入较大的复杂度。

那时候 Kotlin 还是一个相对早期的版本,很多很必要的功能、特性都没有实现(比如 kapt 直到 1.0.6 才相对完善),因此这样的一个 Feature 优先级自然也没有那么高了,更何况这个功能还会有对 Kotlin 的函数类型有潜在影响的风险呢。

后面的故事呢?

最近有本新书叫 Atomic Kotlin,由 Java 编程思想的作者 Bruce Eckel 和 JetBrains 团队的 Svetlana Isakova 合著。。额,怎么说呢,后者也是 Kotlin in Action (貌似还不错)的作者之一,不知道 Atomic Kotlin 是不是要继续砸 Bruce Eckel 招牌(呃,反正那本 Atomic Scala 简直了,感觉就像买了一本 A4 纸)。

好吧,这不是重点了,重点是这位 Svetlana Isakova 小姐姐在 KotlinConf 上面对 Kotlin 的新的(更强大的)类型推断系统做了介绍,也提到了对 Kotlin 函数的 SAM 支持,加上 Andrey 在 Closing Panel 上对 Type classes 的暧昧态度,下一个版本我们大胆猜测下可能是一个类型系统的增强版本,也许对 Kotlin 接口的 SAM 支持也会在 1.4 上获得 Experimental 资格。


转载请注明出处:微信公众号 Kotlin

640?wx_fmt=jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值