Java 8错误:接口继承抽象和默认

时间:2015-09-24 05:23:55

标签: java interface java-8

我试图编写一个集合接口库,使用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

根据我对默认方法的理解,应该允许这样做,因为只有一个扩展接口提供了默认实现,但显然情况并非如此。这里发生了什么?有没有办法让这个做我想做的事?

2 个答案:

答案 0 :(得分:9)

这在Java语言规范的section 9.4.1.3 (Inheriting Methods with Override-Equivalent Signatures)中进行了解释:

  

接口可以使用覆盖等效签名(第8.4.2节)继承多个方法。

     

...

     

同样,当继承具有匹配签名的抽象和默认方法时,我们会产生错误。在这种情况下,可以优先考虑一个或另一个 - 也许我们假设默认方法也为抽象方法提供了合理的实现。但这是有风险的,因为除了巧合的名称和签名之外,我们没有理由相信默认方法与抽象方法的契约一致 - 默认方法在最初开发子接口时可能不存在。 在这种情况下要求用户主动断言默认实现是合适的(通过覆盖声明),这样更安全。

因为MyCollectionList都定义了一个方法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();
    }
    ...
}

答案 1 :(得分:0)

将您的源代码更改为

public interface MyList<E> extends MyCollection<E>,List<E> {
     @Override 
     default boolean isEmpty(){
           return MyCollection.super.isEmpty();
      }
}

有关更多信息,请点击链接, default implementation in interface