Якщо тип реалізує два інтерфейси, і кожен interface
визначає метод, що має ідентичну підпис, то по суті існує лише один метод, і вони не відрізняються. Якщо, скажімо, два способи мають суперечливі типи повернення, то це буде помилка компіляції. Це загальне правило успадкування, переосмислення методу, приховування та декларації, і стосується також можливих конфліктів не лише між двома успадкованими interface
методами, але також interface
і супер class
методом, або навіть просто конфліктами через стирання типу дженериків.
Приклад сумісності
Ось приклад, коли у вас є метод interface Gift
, який має present()
метод (як у поданні подарунків), а також метод interface Guest
, який також має present()
метод (як, наприклад, гість присутній і не відсутній).
Presentable johnny
є і a, Gift
і a Guest
.
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { void present(); }
interface Presentable extends Gift, Guest { }
public static void main(String[] args) {
Presentable johnny = new Presentable() {
@Override public void present() {
System.out.println("Heeeereee's Johnny!!!");
}
};
johnny.present(); // "Heeeereee's Johnny!!!"
((Gift) johnny).present(); // "Heeeereee's Johnny!!!"
((Guest) johnny).present(); // "Heeeereee's Johnny!!!"
Gift johnnyAsGift = (Gift) johnny;
johnnyAsGift.present(); // "Heeeereee's Johnny!!!"
Guest johnnyAsGuest = (Guest) johnny;
johnnyAsGuest.present(); // "Heeeereee's Johnny!!!"
}
}
Вищенаведений фрагмент збирається та запускається.
Зауважте, що є лише один @Override
необхідний !!! . Це тому, що Gift.present()
і Guest.present()
є " @Override
-еквівалентними" ( JLS 8.4.2 ).
Таким чином, johnny
має тільки одну реалізацію з present()
, і це не має значення , як ви ставитеся johnny
, то чи як Gift
або як Guest
, є тільки один метод для виклику.
Приклад несумісності
Ось приклад, коли два успадкованих методу НЕ є @Override
еквівалентними:
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { boolean present(); }
interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
// "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
// both define present(), but with unrelated return types"
}
Далі ще раз підтверджується, що успадковування членів від обов'язку interface
повинно підкорятися загальному правилу декларацій членів. Ось ми Gift
і Guest
визначимо present()
з несумісними типами повернення: один void
за одним boolean
. З тієї ж причини, що ви не можете використовувати один void present()
і boolean present()
один тип, цей приклад призводить до помилки компіляції.
Підсумок
Ви можете успадковувати методи, які є @Override
еквівалентними, за умови звичних вимог методу, що перекриває та приховує. Оскільки вони НЕ @Override
еквівалентні, фактично існує лише один метод реалізації, і, отже, немає чого відрізняти / вибирати.
Компілятору не потрібно визначати, який метод є для якого інтерфейсу, тому що коли вони визначаються як @Override
-еквівалентні, вони є тим самим методом.
Вирішення потенційної несумісності може бути складним завданням, але це зовсім інше питання.
Список літератури