Если тип реализует два интерфейса, и каждый interface
определяет метод с одинаковой сигнатурой, то в действительности существует только один метод, и они не различимы. Если, скажем, два метода имеют конфликтующие типы возврата, то это будет ошибка компиляции. Это общее правило наследования, переопределения методов, скрытия и объявлений, а также применяется к возможным конфликтам не только между 2 унаследованными interface
методами, но также к interface
и супер class
методу или даже просто конфликтам из-за стирания типа дженериков.
Пример совместимости
Вот пример, где у вас есть interface Gift
, у которого есть метод present()
(как при вручении подарков), а также interface Guest
, у которого также есть метод present()
(как у гостя). присутствует и не отсутствует).
Presentable johnny
является одновременно Gift
и 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
-эквивалентны, с учетом обычных требований переопределения и сокрытия методов. Поскольку они ARE @Override
-эквивалентны, фактически существует только один метод для реализации, и, таким образом, нечего отличать / выбирать.
Компилятору не нужно определять, какой метод для какого интерфейса, потому что, как только они определены как @Override
-эквивалентные, они становятся тем же методом.
Устранение потенциальных несовместимостей может быть сложной задачей, но это совсем другая проблема.
Ссылки