Как происходит наследование если оба реализуемых интерфейса объявляют один и тот же метод?

В том случае, когда объявления полностью идентичны, в класс, реализующий эти интерфейсы определяет требуемый метод.

В том случае, если методы возвращают разные типы, тот все зависит от самих типов.

Как известно, начиная с 5 версии Java переопределение ковариантно по отношению к типу возвращаемого значения. Таким образом, в наследнике тип выдаваемого результата может являться наследником. Например, в super классе метод должен возвращать Number, то в переопределённом классе он может возвращать Integer.

Когда возвращаемые типы не наследуются один от другого, как Srting и Integer, то в этом случае данный класс реализовать не получиться.

Для примитивных типов правило ковариантности не действует и при попытке реализовать класс появиться ошибка о несовместимости типов, даже если типы совместимы и их можно присваивать, как int и Long.

Для методов throws, выбрасывающих исключения, работает правило ковариантности. Но следует учитывать, что исключений имеющих примитивные тип не существует. Кроме этого, для исключений, не являющихся наследниками друг друга есть вариант, когда исключения полностью отсутствуют.

interface IntegerResult { Integer foo(); }
interface IntResult { int foo(); }
interface NumberResult { Number foo(); }
interface ThrowsException { void foo() throws Exception; }
interface ThrowsIOException { void foo() throws IOException; }
 
class ResultCovariance implements IntegerResult, NumberResult {
  @Override
public Integer foo() { return 42; }
}
 
class Primitive implements IntegerResult, IntResult {
  @Override
public int foo() { return 42; } // Реализовать этот класс без ошибки невозможно
}
 
class ThrowsCovariance implements ThrowsException, ThrowsIOException {
  @Override
public void foo() throws IOException {} // Общий наследник Exception и IOException.
}

Если метод объявлен как default, то есть имеет реализацию, то невозможно определить какой именно метод нужно вызвать, и компилятор выдаёт ошибку «inherits unrelated defaults».

Данная ошибка появляется даже если обе реализации методов идентичны. Такая ошибка может встретиться даже при работе со стандартными библиотеками Java. При реализации List и Set данную ошибку вызовет метод spliterator().

Поэтому, такой метод должен быть переопределён и для него должна быть определена реализация от конкретного родителя. Для чего можно использовать следующий синтаксис: MyBase.super.doSmth(). Пример его использования приведён ниже.

interface Button {
  default void clickO {
    System.out.println("Button is clicked");
    	}
}
 
interface Link {
  default void click() {
    System.out.println("Link is clicked");
      }
}
 
interface Clickable {
  void click();
}
 
class MyControl implements Button, Link {
  @0verride
  public void click() {
    Button.super.click(); // Явно вызываем нужный метод
      }
}
 
abstract class MyButton implements Clickable, Button { 
  // Ключевое слово abstract не избавляет от ошибки
}
Поделиться уроком

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *