Может ли абстрактный класс содержать конструктор

Обновлено: 28.03.2024

Если да, то как его можно использовать и для каких целей?

да, абстрактный класс может иметь конструктор. Рассматривайте это:

суперкласс Product является абстрактным и имеет конструктор. Конкретный класс TimesTwo имеет конструктор, который просто жестко кодирует значение 2. Конкретный класс TimesWhat имеет конструктор, который позволяет звонящему указать значение.

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

Примечание: поскольку в Родительском конструкторе нет конструктора по умолчанию (или no-arg абстрактный класс, конструктор, используемый в подклассе, должен явно вызывать родительский конструктор.

вы определите конструктор в абстрактном классе, если вы находитесь в одной из следующих ситуаций:

  • вы хотите выполнить некоторые инициализация (в поля абстрактный класс) перед экземпляр подкласса на самом деле имеет место
  • вы определили окончательные поля в абстрактный класс, но вы не инициализировать их в объявлении сам; в этом случае вы должны иметь конструктор для инициализации этих поля
  • вы можете определить более чем один конструктор (с разными аргументы)
  • вы можете (должны?) определите все ваши конструкторы защищенные (изготовление их публика все равно бессмысленна)
  • ваш конструктор(ы) подкласса может вызов одного конструктора абстрактного класс; он может даже обязательно назвать это (если нет конструктора no-arg в абстрактном классе)

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

Да, он может иметь конструктор, и он определен и ведет себя так же, как конструктор любого другого класса. За исключением того, что абстрактные классы не могут быть непосредственно созданы, только расширены, поэтому использование всегда из конструктора подкласса.

да! абстрактные классы могут иметь конструкторы!

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

когда мы создаем объект любого подкласса все конструкторы в соответствующем дереве наследования вызываются в подход сверху вниз. То же самое относится и к абстрактным классам. Хотя мы не можем создать объект абстрактного класса, когда мы создаем объект класса, который является конкретным и подкласс абстрактного класса, конструктор абстрактного класса вызывается автоматически. Следовательно, мы можем иметь конструктор в абстрактных классах.

Примечание: не-абстрактный класс не может иметь абстрактные методы, но абстрактный класс может иметь не-абстрактный метод. Причина аналогична конструкторы, разница в том, что вместо автоматического вызова мы можем вызвать super (). Кроме того, нет ничего похожего на абстрактный конструктор, поскольку он вообще не имеет смысла.

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

хорошим примером абстрактного класса, имеющего конструктор, является календарь класса. Вы получаете Объект календаря путем вызова Calendar.getInstance (), но также имеет защищенные конструкторы. Причина, по которой его конструкторы защищены, заключается в том, что только его подклассы могут вызывать их (или классы в одном пакете, но поскольку это абстрактно, это не применяется). GregorianCalendar является примером класса, который расширяет календарь.

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

абстрактный класс может иметь конструктор, но вы не можете создать объект абстрактного класса, так как вы можете использовать этот конструктор?

дело в том, что когда вы наследуете этот абстрактный класс в своем подклассе, вы можете передавать значения его(абстрактного) конструктору через метод super(value) в своем подклассе, и нет, вы не наследуете конструктор.

таким образом, используя super, вы можете передавать значения в конструкторе абстрактного класса, и, насколько я помню, он должен быть первым оператор в вашем методе или конструкторе.

конструктор НЕ СОЗДАЕТ ОБЪЕКТ. Он используется для инициализации объекта.

да, абстрактный класс всегда имеет конструктор. Если вы не определяете свой собственный конструктор, компилятор даст конструктор по умолчанию абстрактному классу. Выше справедливо для всех классов-вложенных, абстрактных, анонимных и т. д.

абстрактный класс (В отличие от интерфейса) могут иметь non-final нестатические поля, которые нуждаются в инициализации. Для этого вы можете написать свой собственный конструктор в абстрактном классе. Но в этом случае не будет никакого конструктора по умолчанию.

будьте осторожны при расширении выше абстрактного класса, вы должны явно вызвать super из каждого конструктора. Первая строка любого конструктора вызывает super (). если вы явно не вызываете super (), Java сделает это за вас. Ниже код не будет компилироваться:

у вас есть чтобы использовать его, как показано ниже пример:

рассмотрим следующий пример:

суперкласс является абстрактным и имеет конструктор.

конечно, абстрактный класс может иметь конструктор.Обычно конструктор класса используется для инициализации полей.Таким образом, конструктор абстрактного класса используется для инициализации полей абстрактного класса. Вы бы предоставили конструктор для абстрактного класса, если хотите инициализировать определенные поля абстрактного класса до создания экземпляра дочернего класса. Абстрактный конструктор класса также может использоваться для выполнения кода, соответствующего каждому дочернему классу. Это предотвращает код дублирование.

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

в конкретном классе объявление конструктора для конкретного типа Fnord эффективно предоставляет две вещи:

средство, с помощью которого код может запросить создание экземпляра Fnord

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

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

1. Могут ли в языке Java у абстрактного класса быть конструкторы?

Да, в абстрактном классе в Java можно объявить и определить конструкторы. Поскольку создавать экземпляры абстрактных классов нельзя, вызвать такой конструктор можно только при формировании цепочки конструкторов, то есть при создании экземпляра конкретного класса-реализации. Но представьте, что интервьюер задаст затем вопрос: а какой смысл в конструкторе, если создать экземпляр абстрактного класса все равно нельзя? Дело в том, что его всё равно можно использовать для задания начальных значений общих переменных, объявленных в абстрактном классе и используемых различными реализациями. Даже если вы не объявили никакого конструктора, компилятор добавит в абстрактный класс конструктор по умолчанию без аргументов. Без него ваш подкласс не скомпилируется, поскольку первый оператор в любом конструкторе представляет собой неявный вызов super() – конструктора суперкласса по умолчанию в языке Java.

2. Могут ли абстрактные классы в языке Java реализовывать интерфейсы? Должны ли они реализовывать все методы?

Да, абстрактные классы могут реализовывать интерфейсы с помощью ключевого слова implements . Поскольку они абстрактные, то не обязаны реализовывать все методы. Наличие абстрактного базового класса и интерфейса для объявления типа является рекомендуемой практикой. Пример — интерфейс java.util.List и соответствующий абстрактный класс java.util.AbstractList . Поскольку AbstractList реализует все общие методы, то конкретные реализации (например, LinkedList и ArrayList ) не должны реализовать все методы, как в случае, если бы они реализовали интерфейс List напрямую. Это решение сочетает преимущество использования интерфейса для объявления типа и гибкость абстрактного класса для реализации всего общего поведения в одном месте. В книге Джошуа Блоха «Java. Эффективное программирование» есть отличная глава на тему использования интерфейсов и абстрактных классов в Java, для лучшего понимания имеет смысл её изучить.

3. Может ли абстрактный класс быть final?

Нет, не может. Ключевое слово final означает, что класс на вершине иерархии, и у него не может быть наследников. А абстрактный класс без наследников — это сферический конь в вакууме, так как нельзя создать экземпляр abstract class . Таким образом, если класс одновременно abstract и final , то у него нет наследников и нельзя создать его экземпляр. Компилятор Java выдаст ошибку, если сделать класс одновременно abstract и final .

4. Могут ли у абстрактного класса в языке Java быть статические методы?

Да, абстрактные классы могут объявлять и определять статические методы. Только необходимо следовать общим принципам создания статических методов в Java, поскольку они нежелательны при объектно-ориентированном проектировании, ведь переопределение статических методов в Java невозможно. Статические методы в абстрактном классе – явление очень редкое, но, если на это есть уважительные причины, вам ничего не помешает их использовать.

5. Можно ли создать экземпляр абстрактного класса?

Нет, этого делать нельзя. Суть абстрактного класса заключается в том, что он не завершён, и его нужно завершить в классах-наследниках. То есть этот класс не готов к использованию. В нём, например, может отсутствовать реализация каких-то методов. Раз класс не готов к использованию, то нельзя создавать его объект. А вот экземпляры наследников абстрактного класса создавать можно. Компилятор Java выдаст ошибку, если программа попытается создать экземпляр абстрактного класса.

6. Обязательно ли в абстрактном классе должны быть абстрактные методы?

Нет, в абстрактном классе может не быть ни одного абстрактного метода. Сделать класс абстрактным в языке Java можно просто путем использования ключевого слова abstract при объявлении. Компилятор обеспечит выполнение всех структурных ограничений, например, запрета на создание экземпляров этого класса. Кстати, вопрос о том, должны ли быть абстрактные методы в абстрактном классе или интерфейсе – спорный. Мне представляется, что в абстрактном классе должны быть абстрактные методы, поскольку это первое, о чем думает программист, видя абстрактный класс. Это хорошо согласуется с принципом минимизации неожиданностей.

7. Каковы различия между абстрактным классом и интерфейсом в Java?

  • Интерфейс описывает только поведение (методы) объекта, а вот состояний (полей) у него нет (кроме public static final ), в то время как у абстрактного класса они могут быть.
  • Абстрактный класс наследуется (extends), а интерфейс — реализуется (implements). Мы можем наследовать только один класс, а реализовать интерфейсов — сколько угодно. Интерфейс может наследовать (extends) другой интерфейс/интерфейсы.
  • Абстрактные классы используются, когда есть отношение "is-a", то есть класс-наследник расширяет базовый абстрактный класс, а интерфейсы могут быть реализованы разными классами, вовсе не связанными друг с другом.

8. Когда имеет смысл предпочесть абстрактный класс интерфейсу и наоборот?

  • Вы хотите поделиться кодом между несколькими тесно связанными классами.
  • Вы ожидаете, что классы, которые расширяют ваш абстрактный класс, имеют много общих методов или полей, или требуют других модификаторов доступа, кроме public (например, protected и private ).
  • Вы хотите объявить нестатические или не-final поля. Это позволяет вам определять методы, которые могут получить доступ и изменить состояние объекта, которому они принадлежат.
  • Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, интерфейсы Comparable и Cloneable реализуются многими несвязанными классами.
  • Вы хотите определить поведение конкретного типа данных, но вам не важно, кто его реализует.
  • Вы хотите использовать множественное наследование типа.

9. Что такое абстрактный метод в языке Java?

Абстрактный метод – это метод без тела. Вы просто объявляете метод, не определяя его, с использованием ключевого слова abstract в объявлении метода. Все объявленные внутри интерфейса в языке Java методы – по умолчанию абстрактные. Вот пример абстрактного метода в языке Java: Теперь, для реализации этого метода необходимо расширить абстрактный класс и этот метод переопределить.

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

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

Так вот, все работает хорошо, вот только есть сомнение, что как-то не по фен-шую эти конструкторы сделаны как оптимизировать?

Вполне по фен-шую. Если включать в базовый класс какую-либо логику вы не собираетесь, то можете просто заменить его на интерфейс.

А что вы подразумеваете под оптимизацией? Что именно, по вашему мнению, нуждается в улучшении? Какой параметр?

@andreycha Спасибо за ответ! Выбор сделан в пользу абстрактного класса, а не интерфейса, чтобы не дублировать в наследниках N строк с объявлением полей, их геттерами и сеттерами. Классы полностью идентичны по своей сути, разница только в логике ключевого метода

2 ответа 2

По фэн шую, конструктор абстрактного класса должен быть protected , то есть:

На сколько я понял, у вас примерно следующая ситуация:

Основная причина для создания новых классов - разное поведение метода. Если вы вынесете этот метод в функциональный интерфейс, то все равно вам придется объявлять два класса с транзитными конструкторами (которые вызывают super).

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

Таким образом, если идти по пути наследования, то вариант только один - инициализировать параметры через методы уже после создания объекта, т.е. не в конструкторе. Это можно делать как вручную, так и использовать какой-нибудь паттерн.

Другой вариант - не делать несколько классов, а использовать изначальный класс, который абстрактный, т.е. сделать его не абстрактным, а ему в качестве параметра передавать реализацию того самого метода.

You can now choose to sort by Trending, which boosts votes that have happened recently, helping to surface more up-to-date answers.

Trending is based off of the highest score sort and falls back to it if no posts are trending.

Yes, an abstract class can have a constructor. Consider this:

The superclass Product is abstract and has a constructor. The concrete class TimesTwo has a constructor that just hardcodes the value 2. The concrete class TimesWhat has a constructor that allows the caller to specify the value.

Abstract constructors will frequently be used to enforce class constraints or invariants such as the minimum fields required to setup the class.

NOTE: As there is no default (or no-arg) constructor in the parent abstract class, the constructor used in subclass must explicitly call the parent constructor.

@Jonathon: No real benefit is gained by adding complexity for the purposes of the answering the question asked. If the question was about scope, then, yes, it would make sense to contrast the three useful possibilities.

I think all Jonathon was trying to say is that a public constructor on an abstract class doesn't make any sense because you can't instantiate an abstract class directly (can only instantiate through a derived type that itself is not marked as abstract).

I think it would be good to clarify the last sentence, to state that this is only in this example, that generally abstract classes have default constructors if none have been explicitly declared

Along similar lines to the NOTE and Vic's comment, if an abstract class extends another class which doesn't have a default constructor, then the abstract class must have a constructor which calls the non-default constructor of the class it's extending.

You would define a constructor in an abstract class if you are in one of these situations:

  • you want to perform some initialization (to fields of the abstract class) before the instantiation of a subclass actually takes place
  • you have defined final fields in the abstract class but you did not initialize them in the declaration itself; in this case, you MUST have a constructor to initialize these fields
  • you may define more than one constructor (with different arguments)
  • you can (should?) define all your constructors protected (making them public is pointless anyway)
  • your subclass constructor(s) can call one constructor of the abstract class; it may even have to call it (if there is no no-arg constructor in the abstract class)

In any case, don't forget that if you don't define a constructor, then the compiler will automatically generate one for you (this one is public, has no argument, and does nothing).

Yes it can have a constructor and it is defined and behaves just like any other class's constructor. Except that abstract classes can't be directly instantiated, only extended, so the use is therefore always from a subclass's constructor.

Yes! Abstract classes can have constructors!

Yes, when we define a class to be an Abstract Class it cannot be instantiated but that does not mean an Abstract class cannot have a constructor. Each abstract class must have a concrete subclass which will implement the abstract methods of that abstract class.

When we create an object of any subclass all the constructors in the corresponding inheritance tree are invoked in the top to bottom approach. The same case applies to abstract classes. Though we cannot create an object of an abstract class, when we create an object of a class which is concrete and subclass of the abstract class, the constructor of the abstract class is automatically invoked. Hence we can have a constructor in abstract classes.

Note: A non-abstract class cannot have abstract methods but an abstract class can have a non-abstract method. Reason is similar to that of constructors, difference being instead of getting invoked automatically we can call super(). Also, there is nothing like an abstract constructor as it makes no sense at all.


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

При определении абстрактных классов используется ключевое слово abstract :

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

Кроме обычных методов абстрактный класс может содержать абстрактные методы . Такие методы определяются с помощью ключевого слова abstract и не имеют никакой реализации:

Производный класс обязан переопределить и реализовать все абстрактные методы, которые имеются в базовом абстрактном классе. Также следует учитывать, что если класс имеет хотя бы один абстрактный метод, то данный класс должен быть определен как абстрактный.

Зачем нужны абстрактные классы? Допустим, мы делаем программу для обслуживания банковских операций и определяем в ней три класса: Person, который описывает человека, Employee, который описывает банковского служащего, и класс Client, который представляет клиента банка. Очевидно, что классы Employee и Client будут производными от класса Person, так как оба класса имеют некоторые общие поля и методы. И так как все объекты будут представлять либо сотрудника, либо клиента банка, то напрямую мы от класса Person создавать объекты не будем. Поэтому имеет смысл сделать его абстрактным.

Другим хрестоматийным примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами:

Читайте также: