我正在尝试使用
Java 8中的新的默认方法语法编写一个收集接口库,以实现标准Collection API中的大多数方法.以下是我要做的一个小样本:
public interface MyCollection<E> extends Collection<E> { @Override default boolean isEmpty() { return !iterator().hasNext(); } //provide more default overrides below... } public interface MyList<E> extends MyCollection<E>,List<E> { @Override default Iterator<E>iterator(){ return listIterator(); } //provide more list-specific default overrides below... }
然而,即使这个简单的例子也遇到了一个编译错误:
error: interface MyList<E> inherits abstract and default for isEmpty() from types MyCollection and List
从我对默认方法的理解,应该允许这样做,因为只有一个扩展接口提供了默认实现,但显然不是这样.这里发生了什么?有没有办法得到这样做我想要的?
解决方法
这在Java语言规范的
section 9.4.1.3 (Inheriting Methods with Override-Equivalent Signatures)中有所解释:
It is possible for an interface to inherit several methods with override-equivalent signatures (§8.4.2).
…
Similarly,when an abstract and a default method with matching signatures are inherited,we produce an error. In this case,it would be possible to give priority to one or the other – perhaps we would assume that the default method provides a reasonable implementation for the abstract method,too. But this is risky,since other than the coincidental name and signature,we have no reason to believe that the default method behaves consistently with the abstract method’s contract – the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).
因此,既然MyCollection和List都定义了一个方法isEmpty(),一个是默认方法,另一个是抽象的,那么编译器需要子接口来再次覆盖该方法来显式声明它应该继承哪一个.如果您希望继承MyCollection的默认方法,那么可以在重写的实现中调用它:
public interface MyList<E> extends MyCollection<E>,List<E> { @Override default boolean isEmpty() { return MyCollection.super.isEmpty(); } @Override default Iterator<E> iterator(){ return listIterator(); } ... }
如果你想让MyList保持isEmpty()抽象(我不认为你想要的),你可以这样做:
public interface MyList<E> extends MyCollection<E>,List<E> { @Override boolean isEmpty(); @Override default Iterator<E> iterator(){ return listIterator(); } ... }