Два интерфейса с одной и той же сигнатурой метода, реализованные в классе Java - программирование
Подтвердить что ты не робот

Два интерфейса с одной и той же сигнатурой метода, реализованные в классе Java

У меня есть два интерфейса Java и один класс реализации.

(Я использовал Eclipse для запуска программы напрямую, и я не пытался проверять предупреждение компилятора и так далее, явно компилируя из командной строки.)

Почему они работают без проблем? Почему Java разрешает это, даже когда он удовлетворяет "контракту" обоих интерфейсов, но создает неоднозначность в реализации класса?

Обновлен пример.

public interface CassettePlayer {
    void play();
}

public interface DVDPlayer {
    void play();
}

public class CarPlayer implements CassettePlayer,DVDPlayer{

    @Override
    public void play() {
        System.out.println("This plays DVD, screw you Cassette !");
    }

    public static void main(String args[]) {
        CarPlayer cp = new CarPlayer();
        cp.play();

        CassettePlayer firstInterface = new CarPlayer();
        firstInterface.play();

        DVDPlayer secondInterface = new CarPlayer();
        secondInterface.play();
    }
}
4b9b3361

Ответ 1

Этот сценарий специально разрешен в Спецификация языка Java, раздел 8.1.5:

Разрешено для одного объявления метода в классе реализовать методы более чем одного суперинтерфейса. Например, в коде:

interface Fish { int getNumberOfScales(); }
interface Piano { int getNumberOfScales(); }
class Tuna implements Fish, Piano {
   // You can tune a piano, but can you tuna fish?
   int getNumberOfScales() { return 91; }
}

метод getNumberOfScales в классе Tuna имеет имя, подпись и тип возврата, который соответствует методу, объявленному в интерфейсе Fish, а также соответствует методу, объявленному в интерфейсе Piano; считается, что они реализуют оба.

Далее в тексте следует отметить, что если у сигнатур метода были разные типы возвращаемых значений, например double и int, не было бы способа реализовать оба интерфейса в одном классе, а ошибка времени компиляции была бы производится.

Ответ 2

Для этого необходимо понять, для каких интерфейсов.

Интерфейс - это своего рода "контракт", так что можно узнать, какие методы принудительно реализованы в классе с этим интерфейсом.

Итак, если вам нужен класс, реализующий "DVDPlayer" (потому что вам нужен метод "play()" ), вы найдете CarPlayer. То же самое касается необходимости применения класса CassettePlayer. Это техническое объяснение.

Но, конечно, в вашей семантической кодировке вы должны убедиться, что метод CarPlayer "play()" удовлетворяет семантике как DVDPlayer, так и CassettePlayer. Я думаю, что в практическом применении это будет плохая практика.

Конечно, в вашем примере это плохая идея иметь два интерфейса, объявляющих один и тот же метод. Более практично, вы должны были сделать интерфейс "Player" с методом "play()" и иметь два других, более конкретных интерфейса DVDPlayer и CassettePlayer (со специальными методами для DVD-дисков и кассет), которые наследуют от Player. С другой стороны, если вам не нужны специальные методы для DVD-дисков или кассет, тогда вам не нужны два разных интерфейса, реализующих один и тот же метод - просто используйте один интерфейс Player, которого будет достаточно.

Ответ 3

Не существует конфликта, потому что оба они указывают один и тот же контракт, а реализация классов предоставляет только один метод, который вызывается при ссылке через любой интерфейс.

Ответ 4

Почему бы и нет? Класс удовлетворяет контрактам, определяемым обоими интерфейсами.

Ответ 5

Класс реализует оба интерфейса - поэтому проблем нет. Конечно, такого рода вещи следует избегать в более сложных сценариях, где может возникнуть непреднамеренное поведение.

Ответ 7

В этой ситуации нет проблем, поскольку оба интерфейса имеют одну и ту же подпись метода. Но как насчет этого?

interface Animal {
    public void eat() throws IOException;
}

interface Plants {
    public void eat() throws NullPointerException;
}

Какой из них выбран компилятором? Почему он получает ошибку ниже кода?

public class Test implements Animal, Plants {

    public void eat() throws IOException {

    }
}

Компилятор говорит: Исключение IOException несовместимо с предложением throws в Plants.eat()