Абстрактные классы и методы в Java, Наследование

У меня есть класс B, который наследуется от класса A. Суперкласс A абстрактный, содержащий один абстрактный метод. Я не хочу реализовывать абстрактный метод в классе B, поэтому мне также нужно объявить класс B абстрактным. Объявляя абстрактный класс B, у меня работают две вещи (программы компилируются и работают правильно):

1.) Я не объявляю никаких абстрактных методов в классе B, даже если этот класс абстрактный. Я полагаю, это работает, потому что класс наследует абстрактный метод класса A, и этого достаточно, чтобы класс был объявлен как абстрактный: нам не нужны никакие другие абстрактные методы, напрямую объявленные в классе.

2.) Я объявляю тот же абстрактный метод в классе B, как он объявлен в классе A. Это своего рода переопределение (?), Не в том же смысле, что переопределение в java (с использованием того же заголовка, но с другой реализацией. ), здесь я снова использую тот же заголовок метода.

Обе вещи работают, и я не уверен, в порядке ли они оба и предпочтительнее ли одни из них (более правильные), чем другие. Одинаковы ли эти два способа (означают ли они то же самое для Java)?

Здесь я привожу несколько примеров классов, чтобы вам было понятнее то, что я имею в виду:

Дело 1.):

public abstract class A {
    public abstract String giveSum();
}

public abstract class B extends A {

}

Случай 2.):

public abstract class A {
    public abstract String giveSum();
}

public abstract class B extends A {
    public abstract String giveSum();
}

С Уважением

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
10
0
23 174
5

Ответы 5

Функционально они равны, но предпочтительнее первый, потому что он короче и не выглядит странным.

Как насчет того, чтобы «не сбивать с толку читателя, определяется ли новый метод», а не «не странно»? ;-)

joel.neely 06.01.2009 21:39

Выбери №1. Переписывание объявления метода в дочернем классе сбивает с толку. И вам действительно не нужны абстрактные методы в абстрактном классе, независимо от того, является ли родитель абстрактный или нет.

Но имеет ли смысл объявлять класс абстрактным, если в классе не объявлены абстрактные методы (и класс не наследуется от абстрактного класса?)

user42155 06.01.2009 21:35

Ах, сообщение Джареда ниже отвечает на этот вопрос.

user42155 06.01.2009 21:37

Итак, вопрос: что предпочтительнее при подклассе абстрактного класса в java и не хочет предоставлять реализацию?

a) mark subclass as abstract too

b) mark subclass as abstract too AND re-write the method signature marked as abstract?

Я бы выбрал первый:

a) Mark subclass as abstract too.

В первом уже есть объявление абстрактного метода, повторять его нет смысла.

В Java аннотация класса abstract указывает, что экземпляр класса нельзя создать напрямую. Класс может быть объявлен abstract просто потому, что он никогда не должен создаваться (возможно, он содержит только статические методы), или потому что вместо этого следует создавать экземпляры его подклассов.

нет является требованием, чтобы классы abstract содержали методы abstract (обратное является истинно: класс, содержащий один или несколько методов abstract, должен быть abstract.)

Вопрос о том, следует ли дублировать определение абстрактного метода, может быть воспринят как вопрос стиля, но мне было бы трудно придумать аргумент в пользу дублирования определения (единственный аргумент, который я могу придумать, касается случая где иерархия классов может изменить семантику или использование метода, и поэтому вы хотели бы предоставить дополнительную документацию javadoc в классе B.)

Главный аргумент против повторного определения метода abstract заключается в том, что дублирование кода - это плохо - это делает рефакторинг более громоздким и тому подобное (применяются все классические аргументы «не дублировать код».)

Вы правы, эти два случая эквивалентны. Случай 1) более простой, случай 2) - дублирование кода - избегайте этого. Но для этого может быть одна причина:

Если метод в классе A не возвращает String, но позволяет сказать C, класс B может переопределить его (начиная с Java 5) более конкретным типом возврата, допустим, D (класс расширяет C):

public abstract class A {
  public abstract C giveSum();
}

public abstract class B extends A {
  public abstract D giveSum();
}

public class C {
  ...
}

public class D extends C {
  ...
}
en.wikipedia.org/wiki/Covariant_return_type. я думаю, что реализовано только в java 1.5 (java.sun.com/developer/JDCTechTips/2004/tt1201.html#2)
Chii 07.01.2009 17:40

Другие вопросы по теме