/ / Java 8 Грешка: Интерфейс наследява абстрактни и по подразбиране - java, интерфейс, java-8

Java 8 Грешка: интерфейс наследява абстрактни и по подразбиране - java, интерфейс, java-8

Опитвам се да напиша библиотека за събиранеинтерфейси, които изпълняват повечето от методите в стандартния API за колекции, като използват новия синтаксис по подразбиране в 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

От моето разбиране за методите по подразбиране, товатрябва да се допускат, тъй като само един от разширените интерфейси осигурява изпълнението по подразбиране, но очевидно това не е така. Какво става тук? Има ли начин да накарам това да върши това, което искам?

Отговори:

9 за отговор № 1

Това е обяснено в раздел 9.4.1.3 (Методи за наследене с подписи с еквивалентни резултати) от спецификацията за език на Java:

Възможно е интерфейсът да наследи няколко метода с подписи, еквивалентни на преизпълнение (§8.4.2).

...

По същия начин, когато един абстракт и един по подразбиране методсъс съвпадащи подписи се наследили, създаваме грешка. В този случай би било възможно да се даде приоритет на едното или другото - може би ще приемем, че методът по подразбиране дава разумно приложение и на абстрактния метод. Но това е рисковано, тъй като различно от случайното име и подпис, нямаме причина да вярваме, че методът по подразбиране се държи последователно с договора на абстрактния метод - по подразбиране методът може да не е съществувал дори и когато първоначално е бил разработен субпространството. В тази ситуация е по-безопасно да се поиска от потребителя активно да заяви, че изпълнението по подразбиране е подходящо (чрез първостепенна декларация).

И така, тъй като и двете 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

променете изходния си код

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

За повече информация следвайте връзката, стандартно изпълнение в интерфейса