Два интерфейса с теми же именами методов и подписями. Но реализованный единым классом затем, как компилятор определит, какой метод для который интерфейс?
Исключая:
interface A{
int f();
}
interface B{
int f();
}
class Test implements A, B{
public static void main(String... args) throws Exception{
}
@Override
public int f() { // from which interface A or B
return 0;
}
}
Если тип реализует два интерфейса, и каждый интерфейс
определяет метод с идентичной сигнатурой, то в действительности существует только один метод, и они не различимы. Если, скажем, два метода имеют конфликтующие типы возвращаемых данных, это будет ошибка компиляции. Это общее правило наследования, переопределения, скрытия и объявления методов, и оно применяется также к возможным конфликтам не только между двумя унаследованными методами интерфейса , но также интерфейсом
и супер class
, или даже просто конфликты из-за стирания типов обобщений.
Вот пример, где у вас есть интерфейс Gift
, в котором есть метод present ()
(например, представление подарков), а также ] интерфейс Guest
, который также имеет метод present ()
(например, гость присутствует, а не отсутствует).
Презентабельный Джонни
одновременно Дар
и Гость
.
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 ).
Таким образом, Джонни
имеет только одну реализацию из present ()
, и неважно, как вы относитесь к Джонни
, будь то Gift
или Гость
, есть только один метод для вызова.
Вот пример, в котором два унаследованных метода НЕ @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"
}
Это еще раз подтверждает, что наследование членов от интерфейса
должно подчиняться общее правило объявления членов. Здесь у нас есть Gift
и Гость
, определяют present ()
с несовместимыми типами возврата: один void
другой логический
. По той же причине, что вы не можете использовать void present ()
и boolean present ()
в одном типе, этот пример приводит к ошибке компиляции.
Вы можете наследовать методы, которые @Override
-эквивалентны, при условии соблюдения обычных требований переопределения и скрытия методов. Поскольку они ЯВЛЯЮТСЯ @Override
-эквивалентными, фактически существует только один метод, который нужно реализовать, и поэтому нет ничего, из чего можно было бы отличить / выбрать.
Компилятору не нужно определять, какой метод предназначен для какого интерфейса, потому что, если они определены как @Override
-эквивалентные, это один и тот же метод.
Устранение потенциальных несовместимостей может быть сложной задачей, но это уже другая проблема.
Что касается компилятора, то эти два метода идентичны. Будет одна реализация обоих.
Это не проблема, если эти два метода фактически идентичны, в том, что они должны иметь одинаковую реализацию. Если они отличаются по контракту (в соответствии с документацией для каждого интерфейса), у вас будут проблемы.
Здесь нечего идентифицировать. Интерфейсы предписывают только имя метода и его сигнатуру. Если оба интерфейса имеют метод с совершенно одинаковым именем и сигнатурой, реализующий класс может реализовать оба метода интерфейса одним конкретным методом.
Однако, если семантические контракты двух интерфейсных методов противоречат друг другу, вы практически проиграли; тогда вы не можете реализовать оба интерфейса в одном классе.
Ну, если они оба одинаковы, это не имеет значения. Он реализует оба из них с помощью одного конкретного метода для каждого метода интерфейса.