Is adding a trait method with implementation breaking backward compatibility?

橙三吉。 提交于 2020-01-01 02:28:08

问题


I am confused regarding backward compatibility when adding a method with default implementation to a trait. Like:

Previous Version

trait Foo

New Version

trait Foo {
  def verifyConsistency: Option[String] = ??? // provide default implementation
}

The Migration Manager reports this addition as a binary incompatibility. Is that correct?


回答1:


Well yes it is correct.

When you define trait Foo, it will under the hood create both a (JVM) interface Foo and a (JVM) class Foo$class with all the method implementations defined as static methods. The corresponding java code would look like something like this (for your new defintion of Foo):

interface Foo {
  Option<String> verifyConsistency();
}

class Foo$class {
  static Option<String> verifyConsistency(Foo self) {
    Predef.???();
  }
}

When you mix Foo into a concrete class Bar, what happens at the JVM level is that Bar extends the interface Foo, and it implements method verifyConsistency by simply forwarding the call to Foo$class:

class Bar implements Foo {
  Option<String> verifyConsistency() {
    return Foo$class.verifyConsistency(this); // simple forwarding
  }
}

The reason why it is done this way is that the JVM object model does not support multiple inheritance. The traits implementations cannot be simply put in classes that you would extend from, because you can only ever extend a single class on the JVM.

The take away of this situation is that everytime a concrete class mixes a trait, the class defines "stub" methods for each member of the trait (those methods simply forward to the actual implementation, which is a static method).

One consequence is that if you add a new method to a trait, even if you define an implementation it is not enough: concrete classes that mix the trait need to be recompiled (so that a stub for the new method is added to the class). If you don't recompile those classes, your program will fail to run, as you would now have a class that is supposedly concrete (non abstract) AND extend the corresponding interface but actually miss the implementation for the new method.

In your case this means having concrete classes that extend interface Foo but do not have any implementation for verifyConsistency.

Hence the binary incompatibility.



来源:https://stackoverflow.com/questions/18366817/is-adding-a-trait-method-with-implementation-breaking-backward-compatibility

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!