JavaRush /Курси /Java Syntax Zero /Абстрактні класи

Абстрактні класи

Java Syntax Zero
Рівень 18 , Лекція 6
Відкрита

1. Спільний базовий клас

Сьогодні просто день цікавих тем. Пам'ятаєте, як ми колись створили базовий клас ChessItem для спрощення всіх класів шахових фігур? Сподіваюся, що так 🙂

Тепер уявіть, що кожна фігура має метод, який займається її візуалізацією на екрані, наприклад, draw(). Викликаєш метод draw(), і фігура сама себе малює відповідно до своїх поточних координат. Цей метод було б зручно винести в базовий клас.

Якби метод draw() був у базовому класі ChessItem, можна було б перевизначити його в класах фігур і написати такий вишуканий код:

class ChessBoard
{
   public void drawAllChessItems()
   {
      // додаємо фігури до списку
      ArrayList<ChessItem> items = new ArrayList<ChessItem>();
      items.add(new King());
      items.add(new Queen());
      items.add(new Bishop());

      // малюємо їх незалежно від типу
      for(ChessItem item: items)
 {          item.draw();
      }
   }
}

Введення базового класу ChessItem допомагає значно спростити код: не потрібно викликати методи кожного класу окремо, можна зберігати всі об'єкти в одній колекції тощо.

Проте є одне цікаве питання: а що має малювати на екрані метод draw(), оголошений безпосередньо в класі ChessItem? Адже такої фігури в шахах немає, тож і малювати немає чого.

Ба більше, створювати об'єкти типу ChessItem просто не має сенсу. Це не шахова фігура, а лише абстракція — клас, який ми створили для зручності. Так працює абстракція в ООП: ми винесли важливі (загальні для всіх фігур) дані й методи в базовий клас, а відмінності залишили в класах фігур.


2. Абстрактні класи

Абстрактні класи

На такі випадки в Java є спеціальний тип класів — абстрактні класи. Вони створені, щоб спростити програмістам роботу зі схожими класами й скоротити в них обсяг схожого коду.

Абстрактні класи мають три особливості, про які варто знати.

Метод без реалізації

Абстрактний клас може містити оголошення методу без його реалізації. Такий метод називається абстрактним. Замість тіла методу просто ставиться крапка з комою, а перед іменем методу пишуть ключове слово abstract. Приклад:

public abstract class ChessItem
{
   public int x, y; // координати
   private int value; // «цінність» фігури
   public int getValue() // звичайний метод, повертає значення value
   {
      return value;
   }

   public abstract void draw(); // абстрактний метод. Реалізації немає.
}

Абстрактний клас

Кожен метод без реалізації позначається спеціальним ключовим словом abstract. Якщо в класі є принаймні один абстрактний метод, клас теж позначається ключовим словом abstract.

Заборона на створення об'єктів

Створювати об'єкти абстрактного класу не можна. Такий код просто не скомпілюється.

Код Опис
ChessItem item = new ChessItem();
item.draw();
Цей код не скомпілюється
ChessItem item = new Queen();
item.draw();
А так можна

Успадкування від абстрактного класу

Якщо новий клас успадковано від абстрактного класу, потрібно перевизначити всі успадковані абстрактні методи, тобто написати для них реалізацію. Інакше такий клас теж доведеться оголосити абстрактним.

Якщо клас має принаймні один нереалізований метод, оголошений безпосередньо в ньому або успадкований від батьківського класу, такий клас вважається абстрактним.

І навіщо нам потрібні абстрактні класи? Хіба не можна замість них використовувати звичайні? А замість абстрактних методів писати методи, тіло яких складається лише з двох дужок — {}?

Можна. Але ці обмеження подібні на модифікатор private. Ми навмисне забороняли за допомогою private прямий доступ до даних, щоб інші програмісти та їхні класи користувалися тільки нашими public-методами.

Так само й з абстрактним класом. Той, хто написав цей клас, не хоче, щоб створювалися об'єкти цього класу. Навпаки, він розраховує на те, що абстрактні методи його абстрактного класу будуть успадковуватися й перевизначатися.

Перевага цього підходу проявляється у великих проєктах. Що більше класів, то чіткіше доводиться визначати їхні ролі. Ви побачите перевагу цього підходу вже в найближчому майбутньому. Усі через це проходять.


Коментарі (9)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
IronMan57 Рівень 28
17 січня 2025
Нижче в коментарах багато хто пише, що не розуміє навіщо ці абстрактні класи. Напишу, як я це бачу. Абстрактні класи потрібні для того, щоб спростити роботу з об'єктами класів нащадків. Мені прийшов в голову такий приклад. Пишемо гру "Ферма". На фермі маємо тварин різних видів у різній кількості - двоє коней, три корови, п'ятеро свиней, 20 курей і т.д. По ходу гри в якийсь момент потрібно провести перекличку цих тварин - кожна по черзі має подати голос. Звісно, тварини різні - різні класи, голоси різні - у кожного класу свій метод податиГолос(). Якщо у цих класів не буде спільного батька, потрібно буде в програмі для кожного класу тварин писати свій цикл для переклички. Простіше зробити клас ДомашняТварина з методом податиГолос(), тоді щоб зробити перекличку, потрібно буде написати всього один цикл, в якому будуть оброблятись об'єкти всіх класів. Це було про батько-нащадки. Але всі ці тварини відносяться до різних біологічних видів (в програмі - різних класів), не можна створити тварину "не мышонок, не лягушка, а неведома зверюшка". Також кожний клас домашніх тварин (кінь, корова, пес) має свій характерний голос (залишимо поки в стороні всіляких папуг). Тобто і голос тварини - це також абстракція, не можна створити тварину, яка чи то гавкає, чи то мукає. Тому створюється абстрактний клас з абстрактними методами, а решта класів від нього успадковується. І тоді ми можемо, наприклад додати всіх тварин в один масив ДомашняТварина[], а не в окремі масиви для кожного виду, а потім обробити цей масив в одному циклі, а не в декількох. І т.д.
Sava_crosava Рівень 23
31 жовтня 2023
Абстракні класи все ж використовуються, для глибшого розуміння рекомендую почитати про них більше тут (Про абстрактні класи) Простіше буде зрозуміло що це таке і з чим його їсти якщо почитати про інтерфейси (Навіщо потрібні інтерфейси) І для закріплення різниця між ними (Різниця між ними))
Василь Рівень 4
24 жовтня 2023
я так розумію що треба просто знати про абстрактні класи, тому що вони використовуються в житті доволі рідко.
Serhii #2958832 Рівень 51 Expert
10 червня 2023
"Від абстракції до реальності" маленька описка в умові. Клас Shape, а потрібен Person. Requirements: 1. Клас Shape не повинен бути абстрактним. ctrl+С/ctrl+V з умови "Абстрактні фігури" 😀
Grimnir Рівень 10
20 січня 2023
Не все очевидно, але задачі дуже легкі
Beisik Рівень 25
16 січня 2023
Теж не зрозумів в чому суть абстрактного класу.Тобто ти береш його як батьківський клас і всеодно переписуєш всі методи тому що вони так не будуть робити.То на віщо він протрібен?
PAMPERS Рівень 26
21 серпня 2023
Його і дуже рідко використовують в реальній роботі(ну я таке чув)
Anonymous #696530 Рівень 19
14 грудня 2022
Нічого не зрозуміло
Alukard Рівень 37 Expert
25 січня 2022
Що то я не зрозумів що тут є