我有一个系统,其类/接口层次结构分布在 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 魔法来帮助解决我的问题吗?
感谢您的帮助!
Kotlin 的默认接口方法实际上默认情况下不会编译为 Java 默认接口方法。如果他们这样做了,你就不会得到
AbstractMethodError
。
要使 Kotlin 默认方法编译为 Java 默认方法,请添加
-Xjvm-default=all
编译器选项。然后清理并重新编译库 A 和 C。
当你需要重新编译库B时,你也应该使用此选项编译它,或者用
BaseInterface
标记
@JvmDefaultWithCompatibility
,否则可能是二进制不兼容。
另请参阅:https://kotlinlang.org/docs/java-to-kotlin-interop.html#default-methods-in-interfaces