我有一个系统,它的类/接口层次 struct 分布在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中之外,我还有其他 Select 吗?有什么Kotlin 魔法可以帮我解决我的问题吗?

谢谢你的帮助!

推荐答案

在默认情况下,Kotlin的默认接口方法实际上并不编译为Java默认接口方法.如果他们这样做了,你就不会得到AbstractMethodError美元.

要使Kotlin默认方法编译为Java默认方法,请添加-Xjvm-default=all编译器选项.然后只需清理并重新编译A和C库.

do需要重新编译B库时,你也应该用这个选项来编译它,或者用@JvmDefaultWithCompatibility来标记BaseInterface,否则它可能是二进制不兼容的.

另请参阅:https://kotlinlang.org/docs/java-to-kotlin-interop.html#default-methods-in-interfaces

Kotlin相关问答推荐

只能在元素区域中点击的Jetpack Compose列

如何避免使用公共类实现内部接口

"Kotlin中的表达式

Kotlin 函数名后面的大括号是什么意思?

有没有办法在 jetpack compose 中将 TextField 密码点图标增加得更大?

Kotlin - 如何避免在密封类的 when() 语句中转换第二个变量

在 Kotlin 中,为什么在 `+` 之前但在 `.` 之前没有换行符?

如何使用子变量在 Kotlin 中初始化父级

为什么没有remember 的 mutableStateOf 有时会起作用?

错误:cannot find symbol import com.gourav.news.databinding.ActivityDetailBindingImpl;

有没有办法重用 Job 实例?

Android 在将 androidx 生物识别更新为 1.0.0-alpha04 后崩溃

Anko 中的水平线性布局

Kotlin 枚举中的循环引用

Kotlin - 来自 KType 的 KClass<*>

有没有办法在数据类构建时转换属性的值?

Jacoco在Gradle 7.0.2和Kotlin 1.5.10上失败

Kotlin:具有多个不同类型设置器的单个属性

Kotlin类型安全类型别名

Kotlin:如何使用扩展函数扩展枚举类