В этом разделе мы поговорим об еще одном удобном понятии в ООП — абстрактных классах.

Зачем нужны абстрактные классы

Идея абстрактного класса заключается в следующем предположении — для работы иногда вам требуются не полностью готовые классы, а «заготовки» (полуфабрикаты, если хотите). Они уже кое-что умеют, но в «сыром виде» их использовать нельзя. Причем здесь стоит выделить два момента:

  1. Создать экземпляр такого класса нельзя
  2. Такой класс требует доработки под какие-либо конкретные условия.

Например в Java есть весьма наглядный класс java.util.Calendar. В его арсенале достаточно много полезных и нужных функций, но есть одна особенность — он не реализует какой-то конкретный календарь. Думаю, вы знакомы с тем фактом, что на Земле люди живут по разным календарям. Светские власти и католики живут по Григорианскому календарю. Русская православная церковь живет по Юлианскому календарю. А если ваша программа будет работает на марсоходе (что на самом деле так и есть — Java работает на марсоходе Spirit), то ей придется учитывать марсианский календарь. Как вы понимаете календари имеют различия, но вряд ли вы удивитесь, если вам скажут, что возможность прибавить 5 дней к какой-либо дате должна присутствовать во всех вариантах. Т.е. во всех этих календарях есть общий набор функций, который может иметь одинаковую реализацию. Отсюда рождается идея абстрактного класса, который с одной стороны не может создавать объекты, а с другой стороны, может иметь уже готовые функции.
Еще одним примером абстрактного класса может служить уже знакомый нам класс JComponent. Этот класс умеет многое, он только не умеет рисовать что-либо. И если его этому научить — создать класс на его основе и переопределить метод paintComponent, то мы получим то, что нам надо.
Создание абстрактного класса на самом деле достаточно сложная архитектурная задача. Необходимость использовать именно абстрактный класс проявляется не сразу. Требуется провести анализ задачи и набора классов, который позволит принять решение.
А вот техническая сторона достаточно простая — для объявления абстрактного класса достаточно добавить ключевое слово abstract в описании класса.

Если вы попробуете создать объект этого класса, то компилятор выдаст сообщение об ошибке.
Кроме того, что мы можем заставить разработчика НЕ пользоваться нашим классом впрямую, мы можем еще более жестко подойти к наследованию — установить правила, которые заставят класс-наследник реализовать определенные методы.
Для этого необходимо не только класс описать как абстрактный, но и метод, который должен обязательно реализовать наследник. Форма записи достаточно несложная. Здесь только надо отметить, что тело метода отсутствует совсем — сразу за описанием метода ставится точка с запятой. Например:

В нашем примере не только класс объявлен как абстрактный, что запрещает создание экземпляра такого класса, но и требуется переопределить метод processModel.
Внимательный читатель возможно отметил факт, что я в одном случае слово abstract поставил в самом начале, а в втором примере после слова public. Это сделано специально — я хотел продемонстрировать, что можно делать объявления и так и так.

И наконец мы сделаем более сложный пример, который продемонстрирует использование абстрактного класса. В части Полиморфизм мы создали приложение, которое рисовало на форме три вида фигур: треугольник, прямоугольник, овал. В этом приложении мы использовали абстрактный класс JComponent, который не имеет обязательности для переопределения метода для рисования paintComponent. Создадим абстрактный класс, который наследуется от JComponent и имеет абстрактный метод, который надо переопределить в классах-наследниках. Вот такой класс:

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

Треугольник

Прямоугольник

Овал

Класс для формы

В конце класс для запуска нашего приложения

Скачать наше приложение можно по ссылке: ShapeApplication2.
Для первого знакомства с абстрактными классами информации будет достаточно. Позволю еще раз отметить: абстрактные классы являются дополнительным удобством при проектировании иерархии классов и позволяют более строго подходить к этому вопросу. Возможно, что на данном этапе изучения вы не полностью осознаете их полезность, но при накоплении опыта вы наверняка поймете и оцените удобство их использования.

И теперь нас ждет следующая статья: Интерфейсы.