jvm Kotlin接口方法默认值和传递依赖

os8fio9y  于 7个月前  发布在  Kotlin
关注(0)|答案(1)|浏览(74)

我有一个系统,类/接口层次结构分布在3个库上。它的玩具版本看起来像这样:
在库A中:

interface BaseInterface {
  fun foo(): String
}

在库B中:

class Impl : BaseInterface {
  override fun foo(): String {
    return "foo!"
  }
}

在库C中:

class SomethingUnrelated {
  fun doAThing() {
     val i: BaseInterface = Impl()
     println(i.foo())
  }
}

到目前为止,一切顺利。库C依赖于库B和库A。一切正常。
现在假设我发布了一个新版本的库A,并添加了一个带有默认实现的新方法:

interface BaseInterface {
  fun foo(): String
  fun newMethod(): Int = 0
}

我想把它引入到库C中,并修改doAThing来使用它,像这样:

class SomethingUnrelated {
  fun doAThing() {
     val i: BaseInterface = Impl()
     println(i.foo() + " and also " + i.newMethod())
  }
}

如果我更新库C,只引入库A的新版本(不涉及对库B的依赖),我会得到java.lang.AbstractMethodError(这是可以理解的)。我可以重新编译库B,同时更新A和B,但是我有一些其他的限制,这使得这很困难。
所以我的问题是除了重新编译库B并同时将两个库引入C中,我还有其他选择吗?有没有什么Kotlin魔法可以帮我解决问题?
谢谢你的帮助!

d5vmydt9

d5vmydt91#

Kotlin的默认接口方法在默认情况下实际上不会编译为Java默认接口方法。如果他们有,你就不会得到AbstractMethodError
要使Kotlin默认方法编译为Java默认方法,请添加-Xjvm-default=all编译器选项。然后清理并重新编译库A和C。
当你需要重新编译库B时,你也应该使用这个选项编译它,或者用@JvmDefaultWithCompatibility标记BaseInterface,否则它可能是二进制不兼容的。
另请参阅:https://kotlinlang.org/docs/java-to-kotlin-interop.html#default-methods-in-interfaces

相关问题