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

Rya*_*ert 12 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...
}
Run Code Online (Sandbox Code Playgroud)

但是,即使这个简单的例子也遇到了编译器错误:

error: interface MyList<E> inherits abstract and default
       for isEmpty() from types MyCollection and List
Run Code Online (Sandbox Code Playgroud)

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

man*_*uti 10

这在Java语言规范的9.4.1.3节(使用覆盖等效签名继承方法)中进行了解释:

接口可以使用覆盖等效签名(第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();
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果你想MyList保留isEmpty()抽象(我认为你不想要),你可以这样做:

public interface MyList<E> extends MyCollection<E>, List<E> {
    @Override boolean isEmpty();

    @Override default Iterator<E> iterator(){
        return listIterator();
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 真正糟糕的是,"List"没有理由重新声明`isEmpty()`.它的唯一目的似乎是将文档注释从继承的"如果此集合不包含元素返回true"更改为更具体的"如果此列表不包含任何元素,则返回true."如果没有这个,一切都将像以前一样工作但是这个问题的编译错误将会消失,因为`MyCollection.isEmpty()`会覆盖`Collection.isEmpty()`... (2认同)