Абстрактные классы и методы в Java - Вопросы

Всего: 5 вопросов

1. 

Что такое абстрактный класс в Java и можно ли создать его объект?

Абстрактный класс — это класс, объявленный с модификатором abstract. Он служит общим предком для подклассов и описывает, что они умеют, не говоря как. Создать его объект напрямую нельзя: строка new Figure(10, 10) даёт ошибку компиляции Figure is abstract; cannot be instantiated, даже если у класса есть конструктор.

Зато тип абстрактного класса можно использовать для ссылок на объекты наследников — ради этого абстракция и нужна:

Figure figure = new Rectangle(10, 20); // так можно
System.out.println(figure.calculateArea());

Исключение только на первый взгляд — анонимный подкласс: запись new Figure(10, 10) { public double calculateArea() { return 0; } } компилируется, потому что создаётся объект безымянного наследника, а не самого Figure.

2. 

Что такое абстрактный метод, как он объявляется и какие модификаторы с ним несовместимы?

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

abstract тип имяМетода(списокПараметров);

public abstract double calculateArea();

Правила: объявить его можно только внутри абстрактного класса или интерфейса; он должен быть реализован в первом неабстрактном наследнике (промежуточный наследник может остаться абстрактным и передать обязанность дальше); он не может быть одновременно static, final или private — статический метод не переопределяется, final запрещает переопределение, а private не виден наследнику. Метод с пустым телом { } — это не абстрактный метод, а обычный: переопределять его никто не обязан.

3. 

Зачем абстрактному классу конструктор и поля, если объектов у него не бывает?

Конструктор абстрактного класса инициализирует унаследованную часть состояния и вызывается из конструктора наследника через super(...):

public abstract class Figure {
    double dimension1;
    double dimension2;

    public Figure(double dimension1, double dimension2) {
        this.dimension1 = dimension1;
        this.dimension2 = dimension2;
    }

    public abstract double calculateArea();
}

public class Rectangle extends Figure {
    public Rectangle(double dimension1, double dimension2) {
        super(dimension1, dimension2); // вызов конструктора абстрактного класса
    }

    @Override
    public double calculateArea() {
        return dimension1 * dimension2;
    }
}

Если явного вызова super(...) нет, компилятор подставит super() сам — и если конструктора без параметров у абстрактного класса не окажется, наследник не скомпилируется. Сам конструктор абстрактным быть не может: конструкторы не наследуются и не переопределяются.

4. 

Чем абстрактный класс отличается от интерфейса и что выбрать?

Ключевые отличия:

  • Количество: унаследовать можно только один класс, а интерфейсов реализовать сколько угодно.
  • Состояние: у абстрактного класса любые поля, в интерфейсе только константы public static final.
  • Конструктор: у абстрактного класса есть, у интерфейса нет.
  • Модификаторы доступа: в абстрактном классе любые, включая protected и private; в интерфейсе члены по умолчанию public.

После появления default-методов в Java 8 граница стала тоньше, но не исчезла. Абстрактный класс берут, когда наследники — вариации одной сущности с общим состоянием и готовым кодом. Интерфейс берут, когда нужен контракт-роль для не связанных между собой классов или когда одному классу нужно несколько таких ролей.

5. 

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

Да. Правило работает только в одну сторону: класс с хотя бы одним абстрактным методом обязан быть абстрактным, но обратное неверно — класс может быть абстрактным без единого абстрактного метода:

public abstract class BaseConfig {
    public String name() {
        return "default";
    }
}
// new BaseConfig(); — ошибка компиляции: cannot be instantiated

Такой класс тоже нельзя инстанцировать — это законный способ сказать «пользуйтесь наследниками, а не мной». В JDK так сделаны, например, java.util.AbstractList и java.util.Calendar: они содержат готовый код, а наследнику остаётся дописать лишь то, что действительно уникально.

Страница 1 из 1