2015-09-24 3 views
11

Я пытаюсь написать библиотеку интерфейсов коллекции, которые реализуют большинство методов в стандартном API Collection, используя новый синтаксис метода по умолчанию в Java 8. Вот небольшой пример того, что Я иду:Ошибка Java 8: наследование интерфейса Аннотация и по умолчанию

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 

из моего понимания методов по умолчанию, то это должно быть разрешено, так как только один из удлиненных интерфейсы обеспечивают реализацию по умолчанию, но ap это не так. Что тут происходит? Есть ли способ заставить это делать то, что я хочу?

ответ

8

Это объясняется в section 9.4.1.3 (Inheriting Methods with Override-Equivalent Signatures) в спецификации языка Java:

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(); 
    } 
    ... 
} 
+0

Необходимость дублирования всех этих сигнатур методов разочаровывает, но это похоже на то, что я искал. Принято, полагая, что избежать этого невозможно. –

+2

В самом деле, это плохо, потому что нет никаких оснований для того, чтобы 'List' обновлял' isEmpty() '. Единственная цель - изменить комментарий к документации из унаследованного «Возвращает true, если эта коллекция не содержит элементов». Более конкретно «Возвращает true, если этот список не содержит элементов». Без этого все будет работать по-прежнему, но ошибка компиляции из этого вопроса исчезнет, ​​поскольку 'MyCollection.isEmpty()' переопределяет 'Collection.isEmpty()' ... – Holger

+1

@Holger. Вы правы в этом случае. Но для других методов, таких как 'toArray', документация отличается больше с точки зрения контракта метода. Я думаю, что эта проблема возникает как цена за использование методов по умолчанию. – manouti

0

изменить ваш исходный код

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

для получения дополнительной информации перейдите по ссылке, default implementation in interface

+0

вызов 'MyCollection.super.isEmpty() 'избыточно –

+0

да !! будет обновлять код. – snAtchnAren

Смежные вопросы