Kotlin实现接口的类如何无需显式引用访问接口伴生对象成员
解决方案
Kotlin 接口的伴生对象成员默认归属于伴生对象独立作用域,不会自动注入到实现类的作用域中,不需要额外的语言 hack 或者导入配置,只需要调整Globals接口的定义结构,就能完全实现你要的效果:
- 将需要直接访问的属性、方法直接定义为接口自身的成员,编写默认实现
- 若要保留
Globals.xxx形式的静态调用能力,让伴生对象直接实现该接口即可,无需重复写逻辑
修改后的Globals接口代码如下:
interface Globals { // 直接作为接口成员定义,提供默认实现 val mc get() = Bloomware.mc val cPlayer get() = mc.player!! val cWorld get() = mc.world!! fun sendPacket(p: Packet<*>?) { mc.networkHandler!!.sendPacket(p) } // 伴生对象实现接口,支持静态方式访问所有成员 companion object : Globals }
该写法同时支持两种访问场景:
- 实现
Globals接口的类中可以直接调用所有成员,和你给出的示例写法完全匹配,无额外性能开销:
object ResourceCancel : Module(), Globals { @Subscribe private fun onPacketSend(event: EventPacket.Send) { cPlayer.jump() // 直接调用,无需前缀 sendPacket(event.packet) // 方法也可直接调用 } }
- 非实现类的场景下,依然可以通过
Globals.cPlayer、Globals.sendPacket()的形式静态访问成员,和你原先伴生对象的调用体验完全一致。
原理说明
你之前的写法不生效的核心原因是:Kotlin 的伴生对象本质是接口内部持有的一个静态单例实例,它的成员和接口自身的成员是完全隔离的,实现类只会继承接口自身声明的成员,不会自动引入伴生对象的作用域。
上述写法编译后等价于 Java 接口中定义默认方法、默认属性 getter,和你提到的 Java 中实现类直接访问接口成员的实现逻辑完全一致,不会给实现类增加任何内存占用,也不需要实现类重写任何成员。
内容的提问来源于stack exchange,提问作者OffeeX
相关产品推荐
相关产品推荐

