Абстрактные классы

Открыта

— Привет, Амиго! Новая интересная тема.

— Да сегодня просто день интересных тем!!

— Спасибо!

— Да не за что.

— Помнишь ситуацию, когда мы ввели базовый класс ChessItem для упрощения всех классов шахматных фигур?

— Да.

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

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

Пример
class ChessBoard
{
  public void drawAllChessItems()
  {
  //добавляем фигуры в список
  ArrayList items = new ArrayList();
  items.add(new King());
  items.add(new Queen());
  items.add(new Bishop());

  //рисуем их независимо от их типа.
  for (ChessItem item: items)
  {
   item.draw();
  }
 }
}

— Молодец. Именно так. А что бы отрисовал на экране метод draw самого класса ChessItem?

— Не знаю. Такой фигуры ведь в шахматах нет. Значит, и изображения у нее нет.

— Именно. Более того, создавать объекты типа ChessItem – не имеет смысла. Это не фигура из шахмат, всего лишь абстракция — класс, который мы сделали для удобства. Так работает абстракция из ООП: мы вынесли важные (общие для всех фигур) данные и методы в базовый класс, а их различия оставили в их классах.

Абстрактные классы - 1

Для такого случая в Java есть специальный тип классов – абстрактные классы. Вот четыре вещи, которые стоит помнить об абстрактных классах.

1) Абстрактный класс может содержать объявление метода без его реализации. Такой метод называется абстрактным.

Пример
public abstract class ChessItem
{
 public int x, y; //координаты
 private int value; // «ценность» фигуры

 public int getValue() //обычный метод, возвращает значение value
 {
   return value;
 }

 public abstract void draw(); //абстрактный метод. Реализация отсутствует.

}
3
Задача
Java Core,  2 уровень,  5 лекция
Недоступна
Набираем код Ӏ Java Core: 2 уровень, 5 лекция
Java Core: 2 уровень, 5 лекция. Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.

2) Абстрактный метод помечается специальным ключевым словом abstract.

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

3) Создавать объекты абстрактного класса нельзя. Такой код просто не скомпилирует.

Код на Java Описание
ChessItem item = new ChessItem();
item.draw();
Этот код не скомпилируется
ChessItem item = new Queen();
item.draw();
А так можно.

4) Если ты наследовал свой класс от абстрактного класса, то нужно переопределить все унаследованные абстрактные методы — написать для них реализацию. Иначе такой класс тоже придется объявить абстрактным. Если в классе есть хотя-бы один нереализованный метод, объявленный прямо в нем или унаследованный от класса-родителя, то класс считается абстрактным.

— А зачем это все нужно? Зачем нужны абстрактные классы? Разве нельзя вместо них использовать обычные? А вместо абстрактных методов просто писать две скобочки в качестве тела метода — {} ?

— Можно. Но эти ограничения сродни модификатору private. Мы специально запрещали с помощью private прямой доступ к данным, чтобы другие программисты и их классы пользовались только написанными нами public-методами.

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

— Все равно не понятно, зачем усложнять себе жизнь?

— Преимущество этого проявляется в больших проектах. Чем больше классов, тем чётче приходится очерчивать их роли. Ты увидишь преимущество этого, и уже в ближайшем будущем. Все через это проходят.

Комментарии (144)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Прыгун17 уровень
26 июня, 17:12
а че, можно объявлять тип списка Arraylist без вот этой фигни <>?
Евгений17 уровень, Санкт-Петербург
26 июня, 19:27
Да, можно, почитай как объявлялись List и его подобные до 5 Java , а после 5 Java появились в них "фигни")) и Generics чтобы понятнее стало https://www.youtube.com/watch?v=iQIR2Zgb93k&list=PLAma_mKffTOSUkXp26rgdnC0PicnmnDak&index=34
Прыгун17 уровень
26 июня, 19:44
👍
Mike22 уровень, Москва
17 июня, 08:49
Пока что самая лучшая статья про абстоактные классы, которую я только встречал в интернете!!! Большое спасибо!
Юрий Лубенченко16 уровень, Киев
18 июня, 10:48
В комментах чаще принято плеваться на статьи JR)) на самом деле, согласен, здесь эссенция того что нужно - минимальный каркас, а на него уже хорошо наслаивать доп. материалы. Бывает так, что под статьей кто-то оставляет коммент со ссылкой на другой ресурс - потратишь еще 10-20 мин и поймешь, что и без ссылки всё было также понятно)) не всегда так, но иногда просто время теряешь.
Темирлан Батчаев 13 уровень, Черкесск
6 июня, 17:12
Советую посмотреть - здесь
MAX16 уровень, Киров
4 июня, 17:32
Yo dawg
Азамат18 уровень
21 мая, 12:18
набираем код я: Ctrl c / Ctrl v
Драконя 19 уровень
22 апреля, 10:05
Для тех, кому не нравится дублировать код ручками: 1. f12 2.
document.querySelectorAll('.ace_line').forEach(x => console.log(x.textContent));
titix16 уровень
25 апреля, 23:56
что енто?
Глеб16 уровень
18 апреля, 02:01
Я помню себя, когда не въезжал во все эти абстрактные классы и в интерфейсы. Но всё же я уверен, что для начинающих ООП-программистов можно донести смысл всего это. Смысл абстрактных методов - обязать разработчиков, которые будут наследоваться от абстрактного класса, реализовать конкретные методы, но при этом часть функционала за них уже реализована в этом абстрактном классе. Например, нам нужно создать класс, который форматирует определённые данные в табличной форме с использованием разных цветов шрифта и выводит их в браузер. На этом этапе пока нужды в абстрактных классах и методах не видно. Потом заказчик попросил обеспечить форматирование данных не только для браузера, но и для черно-белого принтера. Новый класс для этого будет содержать немного другой алгоритм форматирования и совсем другой способ вывода данных, при этом часть когда, обрабатывающая данные, всё равно останется той же. Реализовать это можно так: 1. Общий алгоритм работы с данными выносим в абстрактный класс `DataPresenter`, например в метод `provideBasicFormatting()`. Там реализовываем общее форматирование для браузера и для принтера. 2. Для браузера создаём класс `DataPresenterForBrowser`, для принтера - `DataPresenterForMonochromePrinter`. Оба этих класса унаследованы от `DataPresenter()` и вызывают его метод `provideBasicFormatting()`, а затем уже добавляют особое форматирование для браузера/принтера. 3. Теперь нам нужно реализовать вывод данных. Можно оставить выбор имени метода, делающего это, на волю разработчикам, а можно обязать их реализовать метод `render()`. Для этого, в класса `DataPresenter` создаём абстрактый метод `render()`. Теперь, разработчики классов `DataPresenterForBrowser` и `DataPresenterForMonochromePrinter` обязаны реализовать метод `render()` под нужное устройство - а иначе просто не скомпилируется программа. Просьба всем, кто только начинает разбираться в ООП, написать, было ли понятным моё объяснение.
Vitalii13 уровень, Галифакс
18 апреля, 02:13
отличное объяснение! спасибо.
Vermel19 уровень, Москва
19 апреля, 06:25
Суть ясна, спасибо!
Людмила16 уровень, Харьков
21 апреля, 18:05
Совсем новичкам всё же лучше с котов начинать :))) А вот тем, кто уже потихоньку врулил - это объяснение помогает приблизить знания к реальной жизни! Так что спасибо;)
Oleg Belashko25 уровень, Stepnogorsk
22 апреля, 17:11
без кота и жизнь не та!
Андрей12 уровень, Самара
27 апреля, 17:43
Amazing, we love you.
Евгений Хайретдинов15 уровень, Нефтекамск
3 мая, 11:55
Супер объяснение! Я так-то сразу въехал в понятие абстрактного класса, но вот зачем создавать метод и не реализовывать его - вот это сначала не понял. Теперь понятно - принудить разработчика, который будет наследоваться от этого абстрактного класса, использовать заранее выбранное название метода.
Игорь Birt18 уровень, Тирасполь
4 мая, 13:00
Не так всё просто))
Василий К.16 уровень
8 мая, 01:50
Отличное объяснение, спасибо!
Fen4kin14 уровень, Екатеринбург
22 мая, 16:14
Объяснил хорошо, вот чтобы понять необходимость абстрактных классов, вообще спору нет 👍 Но чтобы обязать разработчика что-то реализовать лучше использовать интерфейсы, так как меняются они безболезненнее и их можно "наследовать" много. Абстрактные классы больше используются тогда, когда есть какой-то стандартный функционал, который пригодится всем наследникам. Для всего остального есть интерфейсы. PS забудем про дефолтные интерфейсы. Они зло. Их не существует. Они непонятные
Георгий19 уровень, Москва
31 мая, 11:38
По пункту 3 все таки есть вопрос: Т.е. абстрактный класс делался только для того, чтобы в унаследованных классах для браузера и принтера обязательно переопределили метод render()? Это для целостности решения нужно? Почему нельзя не делать родительский класс абстрактным и оставлять наследникам возможность самим решать, нужен им вообще класс render() или нет?
SergeySH27 уровень, Москва
9 апреля, 14:42
В квесте Java Core материала достаточно для решения задач без помощи гугла. Как-то проще задачи решаются чем в Java Syntax. Чувствую скоро начнется веселье ))).
Андрей27 уровень, Санкт-Петербург
17 апреля, 12:37
Как пишут старшие товарищи, до убеждения в обратном конкретно тебе осталась всего пара уровней ))) Любой квест начинается с основ, которые пролетаются быстро, потом подтягиваются алгоритмы и гугл начинает манить. В коре настоящие задачи будут труднее, уверен.
SergeySH27 уровень, Москва
17 апреля, 13:40
Так и есть. Уже осознал на 15 уровне )))
Alukard19 уровень, London
20 мая, 11:50
как успехи на 23?)
SergeySH27 уровень, Москва
21 мая, 15:06
По факту сейчас решаю 17 уровень. Достаточно весело и задачки интересные встречаются
Evgeny Leshok14 уровень, Минск
19 марта, 20:48
Кто не понял - тот поймет! https://www.youtube.com/watch?v=kY07wfP2JiA&t=3s
Александр 25 уровень, Екатеринбург
29 марта, 13:37
Большое спасибо за ссылку. Погулял по каналу этого человека - там много всего полезного. Добавил в избранное.
Evgeny Leshok14 уровень, Минск
15 апреля, 22:32
Рад что помог, удачи в развитии!
Andrej Michniov15 уровень, Vilnius
18 февраля, 23:08
Абстрактный класс, это класс родитель, сделанный для того чтоб экономить время на прописание одинаковых строк для многих его наследников. Но чаще всего у таких классов не должно быть объектов, например тот же класс ChessItem, такой фигуры нету и мы не хотим, чтобы кто-то случайно создал объект ChessItem непонятнаяХрень=new ChessItem();, поэтому мы делаем его абстрактным. От него наследуются все методы(и конкретные, и абстрактные), но по этому классу нельзя создать объект)