Почему абстрактный класс, реализующий интерфейс, может пропустить объявление / реализацию одного из методов интерфейса? - PullRequest
118 голосов
/ 13 октября 2008

Любопытная вещь случается в Java, когда вы используете абстрактный класс для реализации интерфейса: некоторые методы интерфейса могут полностью отсутствовать (т. Е. Нет абстрактного объявления или фактической реализации), но компилятор не жалуется.

Например, с учетом интерфейса:

public interface IAnything {
  void m1();
  void m2();
  void m3();
}

следующий абстрактный класс весело компилируется без предупреждения или ошибки:

public abstract class AbstractThing implements IAnything {
  public void m1() {}
  public void m3() {}
}

Вы можете объяснить, почему?

Ответы [ 7 ]

148 голосов
/ 13 октября 2008

Это потому, что если класс абстрактный, то по определению вы обязаны создать его подклассы для создания экземпляра. Подклассы потребуются (компилятором) для реализации любых интерфейсных методов, которые пропущен абстрактным классом.

Следуя вашему примеру кода, попробуйте создать подкласс AbstractThing без реализации метода m2 и посмотрите, какие ошибки дает вам компилятор. Это заставит вас реализовать этот метод.

33 голосов
/ 13 октября 2008

Прекрасно отлично.
Вы не можете создавать экземпляры абстрактных классов .. но абстрактные классы могут использоваться для размещения общих реализаций для m1 () и m3 ().
Так что , если реализация m2 () различна для каждой реализации, а m1 и m3 - нет. Вы можете создавать различные конкретные реализации IAnything только с другой реализацией m2 и получать их из AbstractThing - в соответствии с принципом DRY. Проверять, полностью ли реализован интерфейс для абстрактного класса, бесполезно.

Обновление : Интересно, я обнаружил, что C # вызывает это как ошибку компиляции. В этом сценарии вы вынуждены скопировать сигнатуры методов и добавить в них префикс «public public» в абстрактном базовом классе .. (что-то новое каждый день:)

7 голосов
/ 09 апреля 2015

Отлично. Чтобы понять вышесказанное, вы должны сначала понять природу абстрактных классов. В этом отношении они похожи на интерфейсы. Это то, что Oracle говорит об этом здесь .

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

Итак, вам нужно подумать о том, что происходит, когда интерфейс расширяет другой интерфейс. Например ...

//Filename: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

//Filename: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

... как видите, это также прекрасно компилируется. Просто потому, что, как и абстрактный класс, интерфейс НЕ может быть создан. Таким образом, не требуется явно упоминать методы от своего «родителя». Однако ВСЕ родительские сигнатуры метода неявно становятся частью расширяющегося интерфейса или реализации абстрактного класса. Таким образом, как только соответствующий класс (тот, который может быть создан) расширяет вышеприведенное, БУДЕТ обязательно обеспечить реализацию каждого абстрактного метода.

Надеюсь, это поможет ... и Аллаху, алам!

4 голосов
/ 12 августа 2017

Учитывая интерфейс:

public interface IAnything {
  int i;
  void m1();
  void m2();
  void m3();
}

Вот как на самом деле это видит Java:

public interface IAnything {
  public static final int i;
  public abstract void m1();
  public abstract void m2();
  public abstract void m3();
}

Таким образом, вы можете оставить некоторые (или все) из этих abstract методов нереализованными, как вы это сделали бы в случае abstract классов, расширяющих другой abstract класс.

Когда вы implement и interface, правило, что все interface методы должны быть реализованы в производном class, применяется только к конкретной реализации class (то есть, которая не является abstract самой ).

Если вы действительно планируете создать из него abstract class, то нет правила, согласно которому вы должны implement использовать все interface методы (обратите внимание, что в таком случае обязательно объявить выведено class как abstract)

4 голосов
/ 08 октября 2013

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

2 голосов
/ 29 октября 2016

Когда абстрактный класс реализует интерфейс

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

abstract class X implements Y {   
    // implements all but one method of Y
}

class XX extends X {   
    // implements the remaining method in Y 
} 

В этом случае класс X должен быть абстрактным, поскольку он не полностью реализовать Y, но класс XX фактически реализует Y.

Ссылка: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

1 голос
/ 13 октября 2008

Абстрактные классы не требуются для реализации методов. Таким образом, даже если он реализует интерфейс, абстрактные методы интерфейса могут оставаться абстрактными. Если вы попытаетесь реализовать интерфейс в конкретном классе (т.е. не абстрактном) и не реализуете абстрактные методы, компилятор скажет вам: либо реализуйте абстрактные методы, либо объявите класс как абстрактный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...