这个问题在某种程度上与Java8接口方法中不允许“同步”的原因有关?
了解默认方法的关键是,主要的设计目标是 接口演变
,而不是“将接口转变为(中等)特性”。虽然两者之间存在一些重叠,并且我们试图适应后者所没有的障碍,但是从这种角度来看,最好理解这些问题。(还要注意,由于接口方法可以被多重继承的事实,无论什么意图,类方法
都 将与接口方法不同。)
默认方法的基本思想是:它是具有默认实现的接口方法,而派生类可以提供更具体的实现。而且由于设计中心是接口的演进,因此一个关键的设计目标是能够在 事后
以源兼容和二进制兼容的方式将默认方法添加到接口。
对于“为什么不是最终的默认方法”的答案太简单了,那就是主体将不再仅仅是默认的实现,而是唯一的实现。尽管答案太简单了,但它为我们提供了一个线索,表明这个问题已经朝着可疑的方向发展了。
最终接口方法令人质疑的另一个原因是它们为实现者带来了不可能的问题。例如,假设您有:
interface A { default void foo() { ... }}interface B { }class C implements A, B { }在这里,一切都很好。
C继承
foo()自
A。现在假定
B已更改为具有
foo默认值的方法:
interface B { default void foo() { ... }}现在,当我们进行重新编译时
C,编译器将告诉我们它不知道要继承什么行为
foo(),因此
C必须重写它(并且
A.super.foo()如果希望保留相同的行为,可以选择委托给它。)但是如果
B已经违约了
final,并且
A不受作者的控制
C吗?现在
C已经无法挽回了。它不能不覆盖就进行编译
foo(),但是
foo()如果它是final
in 则不能覆盖
B。
这只是一个例子,但重点是方法的确定性实际上是一种工具,在单继承类(通常将状态与行为耦合)的世界中,比仅对行为做出贡献且可以相乘的接口更有意义。遗传。很难说出“最终实现器中可能还混入了其他什么接口”,而允许接口方法成为最终方法可能会导致这些问题(它们不会对编写接口的人大发雷霆,而会炸毁该接口的人)。尝试实施该功能的可怜用户。)
禁止使用它们的另一个原因是,它们不会代表您的意思。仅当类(或其超类)未提供方法的声明(具体或抽象)时,才考虑使用默认实现。如果默认方法是final方法,但是超类已经实现了该方法,则默认值将被忽略,这可能不是默认作者在声明它为final时所期望的。(此继承行为反映了设计中心对默认方法(接口演变)的反映。应该可以将默认方法(或对现有接口方法的默认实现)添加到已经具有实现的现有接口中,而无需更改实现该接口的现有类的行为,



