JetBrains 正在 Kotlin 2.5.0 中测试两种名为 Companion Blocks 和 Companion Extensions 的新机制,旨在扩展类型关联成员的定义方式,并改善不同 Kotlin 平台之间的互操作性。该公司表示,这种新设计为此前难以通过传统 Companion Objects 实现的编程模式提供了支持。
新机制带来了什么?
类型关联成员用于定义不属于单个对象的常量、工具和构造函数,例如表示零向量的常量,或根据指定角度创建向量的函数。此前,这类用法依赖于 Companion Objects;而新的伴生块允许以更接近在类型内部定义的形式编写这类成员。
Companion Extensions 则允许向任何类或接口添加关联成员,即使开发者并不拥有原始代码,也允许向来自 Java 或原本不包含 Companion Object 的类型添加关联成员。这意味着无需修改外部类型的基本定义,也能对其进行扩展。
编译和兼容性方面的变化
新机制在编译策略上不同于 Companion Objects。在 JVM 平台上,Companion Blocks 会被编译为 static 成员,因此其行为更接近其他平台上的静态成员。JetBrains 认为,这可能有利于 Kotlin Multiplatform:可以在伴生块中定义预期成员,然后使用包含 static 成员的 Java 类实现这些成员。
不过,这些功能仍处于实验阶段。启用 Companion Blocks 需要使用 -Xcompanion-blocks 选项,而同时使用代码块和扩展则需要使用 -Xcompanion-blocks-and-extensions 选项。
实验性使用的限制
使用 Companion Extensions 时,编译器会生成预发布二进制文件。因此,在该功能正式稳定之前,其他项目或库可能无法将使用这些扩展的库作为依赖项使用。相同限制不适用于公开 Companion Blocks,但其用户同样需要启用该功能。
是否应该迁移 Companion Objects?
JetBrains 不建议立即迁移。Companion Objects 仍是 Kotlin 的重要组成部分,并且会继续获得完整支持。在大多数情况下,Companion Blocks 可能会成为新代码的首选方案,但在某些情况下 Companion Objects 仍然不可或缺,例如伴生对象需要实现接口时,因为它们会被编译为完整的类。
实际上,在许多情况下,只需删除 object 一词即可迁移到 Companion Block,但项目及其依赖的所有代码都需要重新编译。JetBrains 还警告称,生态系统中的部分工具可能尚未准备好处理这种新语法。
为什么这一进展很重要?
这一变化对 Kotlin Multiplatform 开发者和库作者很重要,因为它试图缩小 JVM 与其他平台在静态成员概念之间的差距。不过,目前它的实际价值仍取决于实验阶段,以及构建工具、库和编辑器更新的速度。因此,在功能稳定之前,Companion Blocks 更适合用于试验和评估设计,而不适合作为大规模迁移的安全基础。