Что такое абстрактный класс java
Абстрактный класс в Java
Привет! Это статья про абстрактный класс в Java, а также об абстрактных методах. Это не самая простая тема, потому что она, ну. слегка абстрактная 🙂 Поэтому читайте внимательно!
Что такое абстрактный класс
Вы наверняка уже знакомы с понятием класса. Если нет, почитайте эту статью:
Обычно мы создаем классы для того, чтобы пользоваться их объектами. Например, мы создаем объекты типа String, или Scanner, или FileWriter для дальнейшей работы.
Тем не менее, объекты классов нам нужны не всегда. Иногда нам просто нужен суперкласс (т.е. класс, который мы будем наследовать), в котором будут задаваться какие-то общие для наследников методы и характеристики.
Представим, что у нас есть три типа животных:
1. Cобака (класс Dog)
2. Кошка (класс Cat)
3. Корова (класс Cow)
По навыкам, допустим, Ваш персонаж может:
3. Делать двойне сальто
Это все навыки: навык «красться», навык «бежать». Но навыка «навык» не существует. Верно?
По оружию, допустим, в игре есть такие опции:
Как выглядит абстрактный класс
Создать абстрактный класс очень просто. Просто перед словом «class» нужно дописать «abstract«:
Давайте посмотрим на примере. Создадим класс MyClass (пока без «abstract«):
Абстрактные классы
1. Общий базовый класс
Сегодня просто день интересных тем. Помните ситуацию, когда мы ввели базовый класс ChessItem для упрощения всех классов шахматных фигур? Надеюсь, что да 🙂
Введение базового класса ChessItem помогает очень упростить код: не нужно вызвать методы каждого класса отдельно, можно легко хранить все объекты в одной коллекции и т.п.
Именно. Более того, создавать объекты типа ChessItem не имеет смысла. Это не фигура из шахмат, а всего лишь абстракция — класс, который мы сделали для удобства. Так работает абстракция из ООП : мы вынесли важные (общие для всех фигур) данные и методы в базовый класс, а их различия оставили в их классах.
2. Абстрактные классы
Вот три вещи, которые стоит знать об абстрактных классах.
Метод без реализации
Абстрактный класс
Запрет на создание объектов
Создавать объекты абстрактного класса нельзя. Такой код просто не скомпилируется.
Код | Описание |
---|---|
Этот код не скомпилируется | |
А так можно |
Наследование от абстрактного класса
Если вы наследовали свой класс от абстрактного класса, нужно переопределить все унаследованные абстрактные методы — написать для них реализацию. Иначе такой класс тоже придется объявить абстрактным.
Если в классе есть хотя бы один нереализованный метод, объявленный прямо в нем или унаследованный от класса-родителя, класс считается абстрактным.
И зачем это все нужно? Зачем нужны абстрактные классы? Разве нельзя вместо них использовать обычные? А вместо абстрактных методов просто писать две скобочки в качестве тела метода – <>?
То же и с абстрактным классом. Тот, кто написал этот класс, не хочет, чтобы создавались его объекты. Наоборот, он рассчитывает на то, что от его абстрактного класса будут наследоваться и переопределяться абстрактные методы.
Преимущество этого подхода проявляется в больших проектах. Чем больше классов, тем чётче приходится очерчивать их роли. Вы увидите преимущество этого подхода, и уже в ближайшем будущем. Все через это проходят.
Абстрактный класс в Java
В продолжения статьи об классах и методах в java сегодня затронем тему абстрактного класса:
Абстрактный класс — это класс, в объявлении которого есть ключевое слово abstract. Его отличие от обычного класса в том, что нельзя создать объект или экземпляр данного класса. Все остальное в абстрактном классе остается таким как и в обычном. У него есть методы. Только абстрактный класс может иметь абстрактные методы — у которых нет реализации, только объявление. Это означает, что абстрактный метод должен быть реализован в классе-наследнике. Для того чтобы полностью понимать картину абстрактный классов и методов нужно владеть таким понятием как ООП. Ведь абстрактные классы чаще всего используются при реализации наследования.
Теперь когда мы немного познакомились с теорией, предлагаю перейти к практике:
Выше реализован пример абстрактного класса. Как уже говорилось: чтобы класс стал абстрактным нужно добавить к его объявлению ключевое слово abstract.
Абстрактный класс может содержать как обычные, так и абстрактные методы. Давайте реализуем и те, и другие.
public abstract class AbstractClassExample <
public abstract void abstractMethodExample ( ) ;
Класс, который унаследуется от примера выше должен обязательно реализовать абстрактный метод abstractMethodExample. Реализовывать обычный метод в классе-наследнике не обязательно. В случае, если наследник не реализует обычный метод абстрактного метода — выполняется реализация родителя.
public abstract class AbstractClassExample <
public abstract void abstractMethodExample ( ) ;
class AbstractClassRealization extends AbstractClassExample <
class Main <
public static void main ( String [ ] args ) <
AbstractClassRealization abstractClassRealization = new AbstractClassRealization ( ) ;
abstractClassRealization. abstractMethodExample ( ) ;
abstractClassRealization. classicMethodExample ( ) ;
>
>
Результатом выполнения кода будет:
В случае, если в наследнике переопределен обычный метод, будет выполняться его реализация.
public abstract class AbstractClassExample <
public abstract void abstractMethodExample ( ) ;
class AbstractClassRealization extends AbstractClassExample <
class Main <
public static void main ( String [ ] args ) <
AbstractClassRealization abstractClassRealization = new AbstractClassRealization ( ) ;
abstractClassRealization. abstractMethodExample ( ) ;
abstractClassRealization. classicMethodExample ( ) ;
>
>
В примере выше сработает реализация переопределенного метода в наследнике.
В самом начале мы говорили, что создать экземпляр абстрактного класса нельзя. Это верно. Но, можно создать переменную этого класса. Внимательно посмотрите на пример ниже.
public abstract class AbstractClassExample <
public abstract void abstractMethodExample ( ) ;
class AbstractClassRealization extends AbstractClassExample <
class Main <
public static void main ( String [ ] args ) <
AbstractClassRealization abstractClassRealization = new AbstractClassRealization ( ) ;
abstractClassRealization. abstractMethodExample ( ) ;
abstractClassRealization. classicMethodExample ( ) ;
//мы создали переменную с типом абстрактного класса
AbstractClassExample abstractClassExample = new AbstractClassRealization ( ) ;
//но сработает всеравно метод класса наследника
abstractClassExample. classicMethodExample ( ) ;
>
>
Результатом выполнения кода будет:
Данный или похожий пример очень часто можно увидеть в различных тестах. Здесь важно понимать, что будет выполняться метод экземпляра (new AbstractClassRealization()), а не метод типа (AbstractClassExample).
Еще очень часто на собеседованиях можно услышать вопрос: может ли обычный класс иметь абстрактный метод? Ответ: не может. Абстрактный класс может иметь абстрактный и обычный метод, но обычный класс не может иметь абстрактный метод.
Это все, что хотелось рассказать об абстрактных классах в Java. С большим познанием основ ооп и принципов построения систем, Вы сможете умело управлять различными видами классов. И, однажды, абстрактный класс сможет выручить в сложных ситуациях программирования и проектирования систем.
Доброго времени суток!
Тема весьма сложная для начинающего, потому возник вопрос, для чего все-таки нужны абстрактные классы, наследование — это понятно, но зачем тут нужны абстрактные классы, покажите на примере, где это является необходимостью
Здравствуйте. На первый взгляд: абстрактный класс можно заменить на интерфейс и это действительно так. НО! В абстрактном классе могут быть уже реализованные методы. Тогда как в интерфейсе идет только объявление методов. Сейчас, когда уже есть java11 в интерфейсе может быть один реализованный метод. В абстрактном классе же можно объявить и реализовать сколько угодно методов. Подкреплю теорию примером. Допустим у вас есть класс Animal в котором объявлены методы voice(), walk(), name(). Допустим первые 2 метода вы решили сделать абстрактными, а последний реализовать. Когда класс будет наследовать Animal он должен будет обязательно реализовать методы voice(), walk() так как они абстрактные, но метод name() ему реализовывать не обязательно. Допустим в данном методе будет выводиться строка «Я животное». Ваш товарищ по команде будет наследовать ваш абстрактный класс Animal и ему обязательно подсветит, что нужно реализовать методы voice(), walk(), а метод name() он будет реализовывать уже по усмотрению. Он может как переопределить такой метод, так и оставить реализацию родителя.
Разумеется, пример очень банальный, но на реальных и сложных проектах абстрактный класс часто приходит на выручку:)
Разница между абстрактными классами и интерфейсами
Интерфейс описывает только поведение. У него нет состояния. А у абстрактного класса состояние есть: он описывает и то, и другое.
Возьмем для примера абстрактный класс Bird и интерфейс Flyable :
Давай создадим класс птицы Mockingjay (сойка-пересмешница) и унаследуем его от Bird :
Как видишь, мы легко получаем доступ к состоянию абстрактного класса — к его переменным species (вид) и age (возраст).
Но если мы попытаемся сделать это же с интерфейсом, картина будет другой. Можем попробовать добавить в него переменные:
У нас даже не получится создать внутри интерфейса private-переменные. Почему? Потому что private-модификатор создали, чтобы скрывать реализацию от пользователя. А внутри интерфейса реализации нет: там и скрывать нечего.
Интерфейс только описывает поведение. Соответственно, мы не сможем реализовать внутри интерфейса геттеры и сеттеры. Такова природа интерфейса: он нужен для работы с поведением, а не состоянием.
В Java8 появились дефолтные методы интерфейсов, у которых есть реализация. О них ты уже знаешь, поэтому повторяться не будем.
Абстрактный класс связывает между собой и объединяет классы, имеющие очень близкую связь. В то же время, один и тот же интерфейс могут реализовать классы, у которых вообще нет ничего общего.
Вернемся к нашему примеру с птицами.
Наш абстрактный класс Bird нужен, чтобы на его основе создавать птиц. Только птиц и никого больше! Конечно, они будут разными.
С интерфейсом Flyable все обстоит по-другому. Он только описывает поведение, соответствующее его названию, — «летающий». Под определение «летающий», «способный летать» попадает много объектов, не связанных между собой.
Мы бы не смогли описать их с помощью абстрактного класса. У них нет общего состояния, одинаковых полей. Чтобы дать характеристику самолету, нам, наверное, понадобятся поля «модель», «год выпуска» и «максимальное количество пассажиров». Для Карлсона — поля для всех сладостей, которые он сегодня съел, и список игр, в которые он будет играть с Малышом. Для комара. э-э-э. даже не знаем… Может, «уровень надоедливости»? 🙂
Главное, что с помощью абстрактного класса описать их мы не можем. Они слишком разные. Но есть общее поведение: они могут летать. Интерфейс идеально подойдет для описания всего на свете, что умеет летать, плавать, прыгать или обладает каким-то другим поведением.
Классы могут реализовывать сколько угодно интерфейсов, но наследоваться можно только от одного класса.
Об этом мы уже говорили не раз. Множественного наследования в Java нет, а множественная реализация есть. Отчасти этот пункт вытекает из предыдущего: интерфейс связывает между собой множество разных классов, у которых часто нет ничего общего, а абстрактный класс создается для группы очень близких друг другу классов. Поэтому логично, что наследоваться можно только от одного такого класса. Абстрактный класс описывает отношения «is a».
Стандартные интерфейсы InputStream & OutputStream
Очень простой класс для записи примитивных типов Java и строк. Наверняка ты поймешь написанный код даже без объяснений:
Опять же, ты можешь самостоятельно «поиграть» с этим кодом и проверить, как он будет работать на реальных файлах твоего компьютера.
BestProg
Содержание
Поиск на других ресурсах:
1. Что такое абстрактный класс? Назначение абстрактных классов. Общая форма. Ключевое слово abstract
Абстрактный класс – это класс, содержащий методы, которые не имеют реализации. Абстрактный класс создается с целью создания общего интерфейса между разными реализациями классов, которые будут производными от абстрактного класса. Абстрактный класс создается для определения некоторых общих черт производных от него классов, которые определяют конкретную его реализацию.
Запрещено (нет смысла) создавать объект абстрактного класса.
Общая форма объявления абстрактного класса следующая:
2. Что такое абстрактный метод? Общая форма
Если некоторый класс есть унаследованным от абстрактного, то этот класс должен переопределить все абстрактные методы базового абстрактного класса. В противном случае будет сгенерирована ошибка.
Общая форма объявления абстрактного метода в абстрактном классе имеет следующий вид:
В иерархии наследования (расширения) классов, абстрактные методы являются чем-то общим. Конкретные реализации абстрактных методов помещаются классах, унаследованных от абстрактных классов.
3. Схематическое изображение объявления и использования абстрактного метода в абстрактном классе. Пример
Рисунок. Схема взаимодействия между абстрактным классом и производными классами в Java
4. Пример, который демонстрирует использование абстрактных классов
В классе Figure объявляются:
В классе Triangle() реализованы:
В результате выполнения функции main() класса UseAbstractClass будет выведен следующий результат:
5. Объяснение к примеру из пункта 4
Объяснение к примеру (см. предшествующий пункт) в виде вопросов.
5.1. Зачем в классе Figure методы Area() и ShowName() объявляются абстрактными?
5.2. Почему класс Figure объявляется абстрактным?
5.3. Почему в классе Figure методы Area() и ShowName() не содержат кода реализации (тела метода)?
Если в абстрактном классе метод объявлен как абстрактный (с ключевым словом abstract ), то этот метод не должен содержать реализации (согласно синтаксису Java). Это поясняется тем, что вызов этого метода не имеет смысла.
5.4. Можно ли в абстрактном классе Figure добавлять другие не абстрактные методы?
Да, можно. Абстрактный класс может содержать не абстрактные методы (в отличие от интерфейса ).
Нет, нельзя. То есть, следующая строка
есть ошибкой компилятора Java: «Cannot instantiate the type Figure».
Метод GetArea() получает ссылку с именем f абстрактного класса Figure, который есть базовым в иерархии классов (из класса Figure унаследованы два класса Triangle и Circle).
Затем по ссылке вызывается метод Area() в строке
В функции main() при вызове метода GetArea()
Точно таким же способом связывается экземпляр f2 класса Circle с обобщенной ссылкой f в методе GetArea()
6. Можно ли в абстрактном классе объявлять методы, которые имеют реализацию (тело)?
Да, можно. Абстрактный класс допускает реализацию не абстрактных методов.
7. Пример создания иерархии абстрактных классов
Пример. Ниже приведен пример иерархии абстрактных классов
Использование класса C может быть, например следующим
8. Может ли абстрактный класс не содержать абстрактных методов?
Да, может. Это необходимо в случаях, когда абстрактные методы в классе не нужны, но нужно запретить создание экземпляров этого класса.
9. Какие отличия между использованием абстрактных классов и использованием интерфейсов?
Между абстрактными классами и интерфейсами существуют следующие отличия:
10. Преимущества использования абстрактных классов
Использование абстрактных классов дает следующие преимущества: