添加具有实现的特征方法是否会破坏向后兼容性?

2024-03-20

添加方法时我对向后兼容性感到困惑使用默认实现到一个特质。喜欢:

以前的版本

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(使用前将#替换为@)

添加具有实现的特征方法是否会破坏向后兼容性? 的相关文章

随机推荐