我有一个系统,类/接口层次结构分布在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魔法可以帮我解决问题?
谢谢你的帮助!
1条答案
按热度按时间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