内容提要
Kotlin 2.5.0 引入实验性 companion block 和 companion extension,允许在类或接口上定义静态成员,即使不拥有该类。companion block 编译为静态成员,便于多平台互操作;extension 可扩展任意类。需启用编译器标志。companion object 仍受支持,无需迁移,但多数场景可用 companion block 替代。
延伸解读
编译策略与多平台互操作
companion block 在 JVM 上编译为静态成员,这与 companion object 编译为完整类不同。这一变化对 Kotlin Multiplatform 有实际意义:现在可以定义 expected companion block 成员,并用包含静态成员的 Java 类来 actualize 它们,从而简化跨平台互操作。
实验性标志与二进制限制
启用 companion block 需添加 -Xcompanion-blocks 标志;同时启用扩展则需 -Xcompanion-blocks-and-extensions。使用后者会使编译器生成预发布二进制,导致依赖该库的项目在功能稳定前无法将其作为依赖消费。仅暴露 companion block 不受此限制,但消费者仍需启用对应标志。
迁移建议与工具链准备
现有 companion object 无需迁移,官方完全支持。若想改用 companion block,多数情况下删除 object 关键字即可,但项目及依赖代码需重新编译。生态工具可能尚未适配 companion block,官方正推动主要工具尽快支持。
companion object 的不可替代场景
虽然多数场景可用 companion block 替代 companion object,但若伴生对象需要实现特定接口,则只能使用 companion object,因为它编译为完整类。新代码可优先考虑 companion block,但需根据此限制做出选择。
Q&A
Kotlin 2.5.0 引入了哪些新的伴生机制?
Kotlin 2.5.0 引入了实验性的 companion block(伴生块)和 companion extension(伴生扩展),允许在类或接口上定义静态成员,即使不拥有该类。
companion block 和 companion object 在编译上有什么不同?
companion block 编译为静态成员,类似于其他平台的静态成员;而 companion object 编译为一个完整的类。
如何使用 companion block 和 companion extension?需要什么编译器标志?
需要传递编译器标志:-Xcompanion-blocks 允许 companion block;-Xcompanion-blocks-and-extensions 允许两者。使用扩展会产生预发布二进制文件,可能无法作为依赖被消费。
companion object 会被弃用吗?需要迁移吗?
不会。companion object 仍是 Kotlin 的组成部分,支持完全保证,无需迁移。但大多数场景下 companion block 更合适,新代码可优先使用。
companion extension 可以用于哪些类?
可以为任何类或接口定义 companion extension,无论你是否控制它,无论它来自 Kotlin 还是 Java,也无论它是否已有 companion object。
在 Kotlin Multiplatform 中,companion block 有什么优势?
可以定义 expected companion block 成员,并使用包含静态成员的 Java 类来 actualize 它们,从而改善多平台互操作性。