Каждый, кто имеет хоть минимальные знания в программировании, задавался вопросом о том, зачем существуют абстрактные базовые классы. Каково их предназначение? Как создать абстрактный класс? Какие преимущества они дают на практике? Зачем они необходимы в программировании и какие особенности их реализации необходимо учитывать?
Абстрактные классы
Так в программировании называют единицу программного кода, на основе которой не могут создаваться объекты. Следует отметить, что наследники данного класса могут быть не абстрактными. Поэтому создание объектов на их основе является вполне возможным. Если рассматривать пример из Java, то построим такую модель: мы можем описать конструкторы в классе А. Но вот воспользоваться ими мы не сможем. Выходом из этой ситуации является объявление какой-то переменной как ссылки. Причем необходимо четко прописать, чтобы она указывала на объект класса А. А вот как это можно сделать? В этом нам поможет приведение. При этом необходимо учитывать, что класс-родитель всегда считается более универсальным, чем потомок. Во многих языках программирования приведение используется автоматически. Но если нет уверенности в наличии такого механизма, значит, необходимо явно указать ссылку на объект.
Абстрактные методы
Что они собой представляют? Абстрактными называют те методы, которые не имеют реализации в рассматриваемом классе. Так, после круглых скобок (в которых перечисляются используемые в них аргументы) ставят не открывающие фигурные (после чего размещается блок описания метода), а только точку с запятой. Таким образом, в данном случае отсутствует информация о том, что он делает. Тут можно задать вопрос: "А зачем метод без реализации?" Ведь он не подлежит использованию! Конечно, в том классе, где он был описан, такое не является возможным. А вот если рассматривать эту ситуацию с точки зрения потомка, то его можно будет вызвать. И функционировать он будет по конкретному описанию, имеющемуся в данном классе.
Особенности абстрактных методов
Существуют ограничения в их использовании. Рассмотрим это на примере языка программирования Java. Здесь есть такое требование: если в классе есть хотя бы один такой метод, то он обязательно должен быть абстрактным. А в каких случаях уместно использовать такие конструкции? Давайте разберёмся с этим на примере классов домашних животных. Для начала следует уяснить, что нет такого звука, который бы издавали они все. Поэтому в самом общем классе не задаётся реализация метода звучания. Но для него создаётся тело, которое обособленно с помощью блоков. А уже в последующем, когда будет создаваться класс собаки, кота или хомячка, будет прописываться отдельный метод для него, в рамках которого будут раскрываться все особенности.
Интерфейс
В программировании создано много инструментов, цель которых – помочь человеку сделать продукт хорошего качества. И в рамках рассматриваемой темы необходимо уделить внимание и данному аспекту, чтобы каждый знал отличие абстрактного класса от интерфейса. Так, особенностью последнего является то, что у него не может быть свойств, и у методов не определены тела. Исследуя, чем отличается абстрактный класс от интерфейса, следует остановиться ещё на одной особенности. Так, первый наследуется, тогда как второй – реализуется. Человеку неопытному может показаться это несущественным. Но дело в том, что наследоваться может только один класс, а реализовываться – сколько угодно. Вот чем отличается интерфейс от абстрактного класса. Java имеет ещё те особенности, что в нём могут быть описаны исключительно абстрактные публичные методы и статические константы. Но при этом интерфейсы также могут наследоваться. При этом необходимо указывать, что используемые операторы публичны с помощью public.
Множественное наследование интерфейсов
Такая функция не является доступной для классов во многих языках программирования (например, в рассматриваемом нами Java). Это связано с возникновением ряда проблем. В качестве таковых указывают на неоднозначности, которые возникают при наследовании. Это и послужило причиной введения множественного наследования интерфейсов. Это частично решает имеющиеся проблемы, но не все. Так, благодаря принципам инкапсуляции и полиморфизма, интерфейсы могут быть успешно реализованы в разных классах по различным методикам (хотя они и будут обладать одним и тем же именем). Но не стоит забывать и об имеющихся проблемах. Так, при работе с несколькими интерфейсами придётся всегда указывать, кого же мы имеем в виду. Также проблемы будут и при попытке работать с двумя одноименными методами – в таком случае ими невозможно будет воспользоваться. Поэтому на такие случаи необходимо позаботиться о наличии общей реализации.
Абстрактные данные
Это понятие ключевое в программировании. В данном случае под абстракцией понимают независимое рассмотрение и разделение интерфейса и его реализации. Давайте рассмотрим пример. У нас есть телевизор, который является объектом или модулем. Он обладает интерфейсом. В качестве такового выступают средства управления им, а также воспроизведения звука и изображения. Чем более совершенный интерфейс применяется, тем удобней телевизор в процессе использования. Мы можем переключать программы, нажимая на какие-то кнопки. При этом нет нужды думать про физические процессы в телевизоре. О них заботятся специалисты, которые собирают устройство. Нас как пользователей интересуют только свойства. Возвращаясь к программированию, можно сказать, что ими по такой аналогии являются интерфейс и реализация. Также, если человек уверен в своих знаниях, то он может «снять» крышку у нашего гипотетического телевизора и усовершенствовать его. Хотя это может приводить к локальным успехам, в большинстве случаев конечный результат негативный. Поэтому в программировании поддерживается запрет доступа и скрытие внутренних компонентов для абстрактных данных. Принцип этого механизма предусматривает наличие способов предотвращения умышленного или случайного изменения внутренних компонентов. И когда говорят про абстрактные типы данных, то подразумевают их совокупность с множеством операций, которые могут быть выполнены над ними.
Объекты
Мы уже рассмотрели абстрактный класс и интерфейс в целом и общем. Сейчас давайте немного детализируем наши знания. Для начала уделим внимание объектам. Под ними в общем случае понимают часть окружающей реальности, которая существует в пространстве и времени. Но формально определить объекты в рамках программирования довольно сложно (с философско-теоретической точки зрения). Поэтому это делается благодаря его свойствам. В качестве примера можно привести следующее: объект может быть однозначно идентифицирован (обладает уникальным именем), он находится в определённом состоянии и использует определённую модель поведения.
Наследование
Поскольку программирование строится на построении иерархического дерева связей между объектами, то поднимается вопрос о том, чтобы нижележащим типам были переданы свойства родительских библиотек кода. Под наследованием понимают отношения, когда кто-то один повторяет поведение и структуру чего-то другого. В обычной жизни это можно встретить повсеместно. Подобное было перенесено и в программирование относительно абстрактных элементов. В качестве сравнения можно привести тот факт, что нет такого организма, как птица. Это абстрактное название. В качестве конкретного экземпляра приводят чайку, соловья или воробушка. Благодаря наличию наследования мы можем использовать библиотеки классов, а также развивать их для конкретной программы. Такой инструмент позволяет нам создавать новые объекты, попутно дополняя или изменяя свойства уже созданного. Наследник получает все методы и поля своего предка и при необходимости обзаводится своими собственными атрибутами. Благодаря тому что есть абстрактные элементы и принцип наследия, существуют широкие возможности для модификации в рамках объектно-ориентированного программирования. К тому же это позволяет гибко подходить к решению поставленных задач. При наследовании в новый класс передаются данные и функции.
Полиморфизм
Он необходим для того, чтобы применять одинаковые функции для решения различных типов задач. В данном случае предусматривается наличие возможности совершения различных действий, содержание которых будет зависеть от типа объекта, с которым ведётся работа. Под полиморфизмом понимают свойство элементов, которые имеют одного общего родителя, выполнять похожие в смысловом значении проблемы различными способами. Проведём аналогию с животными. Есть такое действие – бежать. Все мы понимаем, как оно происходит. Но разными животными (львом, слоном, шимпанзе, крокодилом, черепахой) это действие будет выполняться по-разному. В данном случае за их перемещение отвечает разработчик, который при надобности может вызвать для конкретного случая определённую подпрограмму, разработав алгоритм и успешно реализовав его. Это делается с помощью набора методов. При этом в каждом отдельном классе программистом указывается, какому объекту какие свойства присущи. Меняя что-то в потомках, можно добиться выполнения определённых, нужных в данном случае действий. Такое влияние называется полиморфизмом объектов. В целом абстрактный класс является чрезвычайно полезным инструментом программирования.