JavaRush /Курси /JAVA 25 SELF /Абстрактні класи та методи: синтаксис, приклади

Абстрактні класи та методи: синтаксис, приклади

JAVA 25 SELF
Рівень 19, Лекція 1
Відкрита

1. Синтаксис абстрактного класу

Розберімося, що таке абстрактний клас у Java й навіщо він узагалі потрібен. Уявіть конструктор LEGO: маєте набір деталей (наприклад, «колеса», «кубики») та спеціальні елементи для конкретних моделей. Абстрактний клас — це узагальнена інструкція щодо роботи з деталями без опису складання конкретної моделі: кубики зчіплюються пазами, колеса кріпляться до осей, деталі можна нарощувати шарами. Абстрактний клас задає саме ці загальні правила й обовʼязкові кроки, але не розписує складання конкретної моделі. Конкретні моделі — це підкласи: вони беруть загальну інструкцію та заповнюють відсутні кроки.

У Java абстрактний клас — це клас, який не можна створити безпосередньо (не можна зробити new AbstractClass()), але від нього можна успадковуватися й реалізовувати його «нереалізовані» методи.

Абстрактні класи потрібні, коли:

  • У групи обʼєктів є спільна поведінка або стан, але частина логіки відрізняється.
  • Ви хочете реалізувати частину функціональності «за замовчуванням», а частину залишити на реалізацію нащадкам.
  • Ви хочете заборонити створення обʼєктів цього класу безпосередньо (наприклад, «Птах» як такий не існує самостійно, а от «Кіт» — існує).

Як оголосити абстрактний клас

Усе просто: перед словом class пишемо ключове слово abstract.

public abstract class Animal {
    // Поля (наприклад, імʼя тварини)
    protected String name;

    // Конструктор
    public Animal(String name) {
        this.name = name;
    }

    // Абстрактний метод — лише оголошення без реалізації!
    public abstract void makeSound();

    // Звичайний (реалізований) метод
    public void sleep() {
        System.out.println(name + " спить: Zzz...");
    }
}

Особливості:

  • Абстрактний клас може містити як реалізовані методи, так і абстрактні.
  • Абстрактний клас може містити поля, конструктори й навіть static-методи.
  • Не можна створити обʼєкт абстрактного класу безпосередньо:
  • Animal a = new Animal("Хтось"); // Помилка!

Як оголосити абстрактний метод

Абстрактний метод — це метод без тіла, тобто без фігурних дужок і коду всередині. Він оголошується ключовим словом abstract і обовʼязково закінчується крапкою з комою ;.

public abstract void makeSound();
  • Абстрактні методи можна оголошувати лише всередині абстрактного класу.
  • Клас, що успадковує абстрактний клас, зобовʼязаний реалізувати всі абстрактні методи, інакше він теж стає abstract.

2. Успадкування абстрактних класів: як це працює

Подивімося на конкретний приклад. Припустімо, що маємо абстрактний клас Animal з абстрактним методом makeSound(). Тепер створімо клас‑нащадок Dog, який реалізує цей метод:

public class Dog extends Animal {
    public Dog(String name) {
        super(name); // Виклик конструктора базового класу
    }

    @Override
    public void makeSound() {
        System.out.println(name + " гавкає: Гав-Гав!");
    }
}

І ще один клас‑нащадок:

public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " нявчить: Няв!");
    }
}

Тепер можемо використати ці класи в програмі:

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("Рекс");
        Animal cat = new Cat("Мурка");

        dog.makeSound(); // Рекс гавкає: Гав-Гав!
        cat.makeSound(); // Мурка нявчить: Няв!

        dog.sleep(); // Рекс спить: Zzz...
        cat.sleep(); // Мурка спить: Zzz...
    }
}

Зверніть увагу:
Можемо оголошувати змінні типу Animal, але створювати обʼєкти — лише конкретних (не абстрактних) нащадків.

Схема: як це виглядає


.         Animal (abstract)
            /         \
         Dog         Cat
 (реалізує makeSound) (реалізує makeSound)

3. Коли використовувати абстрактний клас, а коли інтерфейс?

Це одне з найпопулярніших запитань на співбесідах — і недарма! Розберімося:

  • Абстрактний клас — коли в обʼєктів є спільний стан (наприклад, поля), спільна логіка (методи з реалізацією), і ви хочете дати «скелет» поведінки з можливістю доопрацювання.
  • Інтерфейс — коли ви хочете задати лише набір методів (контракт), без реалізації та стану. Починаючи з Java 8, інтерфейси отримали default/static-методи, але все одно інтерфейс — про «що має вміти обʼєкт», а не «як він це робить».

Приклад з життя:
«Птах» — абстрактний клас: у всіх птахів є дзьоб, крила, і вони можуть літати (але по‑різному).
«Літаючий» — інтерфейс: не лише птахи вміють літати, а й літаки та супергерої! Літають усі по‑різному, та головне — вони це вміють.

4. Практичні приклади

Приклад 1: Абстрактний клас із частковою реалізацією

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

public abstract class Transport {
    protected String name;
    protected int speed;

    public Transport(String name, int speed) {
        this.name = name;
        this.speed = speed;
    }

    // Абстрактний метод — реалізація в нащадках
    public abstract void move();

    // Реалізований метод
    public void stop() {
        System.out.println(name + " зупинився.");
    }
}

public class Car extends Transport {
    public Car(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " їде дорогою зі швидкістю " + speed + " км/год.");
    }
}

public class Bicycle extends Transport {
    public Bicycle(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " крутить педалі зі швидкістю " + speed + " км/год.");
    }
}

Використання:

Transport car = new Car("Toyota", 120);
Transport bike = new Bicycle("Stels", 25);

car.move(); // Toyota їде дорогою зі швидкістю 120 км/год.
bike.move(); // Stels крутить педалі зі швидкістю 25 км/год.

car.stop(); // Toyota зупинився.
bike.stop(); // Stels зупинився.

Приклад 2: Абстрактний метод area()

public abstract class Shape {
    public abstract double area();
}

public class Circle extends Shape {
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width, height;
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double area() {
        return width * height;
    }
}

Використання:

Shape c = new Circle(3);
Shape r = new Rectangle(4, 5);

System.out.println("Площа кола: " + c.area());
System.out.println("Площа прямокутника: " + r.area());

5. Особливості та нюанси абстрактних класів

  • Абстрактний клас може містити будь‑які модифікатори доступу: public, protected, private (наприклад, для полів).
  • Можна оголосити абстрактний клас без абстрактних методів. Це буває корисно, якщо ви просто хочете заборонити створення екземплярів базового класу.
  • Якщо клас успадковує абстрактний клас, але не реалізує всі абстрактні методи, його також слід оголошувати як abstract.
  • Абстрактний клас може мати конструктори. Вони викликаються під час створення обʼєкта‑нащадка (через super(...)).
  • Абстрактні методи не можуть бути private (інакше їх неможливо перевизначити в нащадку).
  • Абстрактні методи не можуть бути static (статичні методи не перевизначаються) і не можуть бути final (адже final забороняє перевизначення).
  • Абстрактний клас може реалізовувати інтерфейси, але не зобовʼязаний реалізовувати їхні методи — це можуть зробити нащадки.

Таблиця: порівняння абстрактного класу та інтерфейсу

Абстрактний клас Інтерфейс
Ключове слово
abstract class
interface
Може містити поля Так (будь‑які) Починаючи з Java 8 — лише static/final
Методи з реалізацією Так Починаючи з Java 8 — default/static
Абстрактні методи Так Так
Множинне наслідування Ні Так (можна реалізувати багато інтерфейсів)
Конструктори Так Ні
Можна створити обʼєкт Ні Ні

6. Типові помилки під час роботи з абстрактними класами та методами

Помилка № 1: спроба створити екземпляр абстрактного класу.
Якщо ви напишете new Animal("Хтось"), компілятор одразу повідомить, що абстрактні класи для цього не призначені. Памʼятайте: абстракція — це «скелет», а не «живий організм».

Помилка № 2: забули реалізувати всі абстрактні методи в нащадку.
Якщо ваш клас не реалізує хоча б один абстрактний метод базового класу, його слід оголосити як abstract, інакше отримаєте помилку компіляції.

Помилка № 3: оголосили абстрактний метод поза абстрактним класом.
У Java не можна оголосити абстрактний метод у звичайному (неабстрактному) класі — компілятор одразу повідомить про помилку.

Помилка № 4: спроба зробити абстрактний метод private або static.
Абстрактні методи не можуть бути private (їх неможливо перевизначити) і не можуть бути static (статичні методи не перевизначаються). Також вони не можуть бути final, адже final забороняє перевизначення.

Помилка № 5: забули про модифікатор доступу для абстрактного методу.
Якщо ви явно не вкажете модифікатор, метод матиме пакетну видимість (package‑private), що інколи не те, що ви хотіли отримати.

1
Задача
JAVA 25 SELF, 19 рівень, 1 лекція
Недоступна
Шифрувальна машина: метод з параметром 🔐
Шифрувальна машина: метод з параметром 🔐
1
Задача
JAVA 25 SELF, 19 рівень, 1 лекція
Недоступна
Система керування «Розумним домом» 📱
Система керування «Розумним домом» 📱
1
Задача
JAVA 25 SELF, 19 рівень, 1 лекція
Недоступна
Геометричний редактор: фігури та їхні площі 📐
Геометричний редактор: фігури та їхні площі 📐
1
Задача
JAVA 25 SELF, 19 рівень, 1 лекція
Недоступна
Кадрова система IT-компанії 💼
Кадрова система IT-компанії 💼
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ