添加方法时我对向后兼容性感到困惑使用默认实现到一个特质。喜欢:
以前的版本
trait Foo
新版本
trait Foo {
def verifyConsistency: Option[String] = ??? // provide default implementation
}
The 迁移经理 https://github.com/typesafehub/migration-manager将此添加报告为二进制不兼容。那是对的吗?
嗯,是的,这是正确的。
当你定义特质时Foo
,它将在后台创建一个(JVM)接口Foo
和一个(JVM)类Foo$class
所有方法实现都定义为静态方法。相应的java代码看起来像这样(对于你的新定义Foo
):
interface Foo {
Option<String> verifyConsistency();
}
class Foo$class {
static Option<String> verifyConsistency(Foo self) {
Predef.???();
}
}
当你混合时Foo
进入一个具体的类Bar
,在 JVM 级别发生的事情是Bar
扩展接口Foo
,并且它实现了方法verifyConsistency
只需将呼叫转接至Foo$class
:
class Bar implements Foo {
Option<String> verifyConsistency() {
return Foo$class.verifyConsistency(this); // simple forwarding
}
}
之所以这样做是因为JVM对象模型不支持多重继承。特征实现不能简单地放入您要扩展的类中,因为您只能在 JVM 上扩展单个类。
这种情况的要点是,每当一个具体类混合一个特征时,该类就会为该特征的每个成员定义“存根”方法(这些方法只是转发到实际的实现,这是一个静态方法)。
一个后果是,如果向特征添加新方法,即使定义实现也是不够的:需要重新编译混合该特征的具体类(以便将新方法的存根添加到类中) 。如果您不重新编译这些类,您的程序将无法运行,因为您现在拥有一个据称是具体(非抽象)的类并扩展了相应的接口,但实际上错过了新方法的实现。
在您的情况下,这意味着拥有扩展接口的具体类Foo
但没有任何实施verifyConsistency
.
因此二进制不兼容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)