JavaRush /Курси /JAVA 25 SELF /Поняття наслідування: синтаксис extends

Поняття наслідування: синтаксис extends

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

1. Що таке наслідування?

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

Це ніби ви готуєте новий торт на основі перевіреного рецепта: берете все найкраще, додаєте кілька нових інгредієнтів — і вуаля: у вас вже «Торт за бабусиним рецептом із секретним інгредієнтом».

  • Батьківський клас — містить спільні властивості та поведінку.
  • Підклас — наслідує все це, а також може додати щось своє або змінити поведінку.

Ось приклад: «Кішка — тварина». Усі кішки — тварини, але не всі тварини — кішки. Тварина може бути базовим класом, а Кішка — її підкласом. Так само й Собака.
Або так: «Коло — фігура». Кожне коло — фігура, але не кожна фігура — коло. Фігура може бути батьківським класом, а Коло й Трикутник — його нащадками. У Java ці зв’язки реалізуються за допомогою ключового слова extends.

Навіщо потрібне наслідування?

Питання на мільйон: чому не можна просто копіювати код із одного класу до іншого? Навіщо взагалі вигадали наслідування?

  • Повторне використання коду: Усе спільне виноситься в базовий клас. Не потрібно дублювати поля й методи — вони автоматично з’являються в підкласах. Наприклад, у програмі для університету базовим класом може бути людина, яка має щонайменше імʼя та день народження, а «студент» і «викладач» — підкласи з власними властивостями.
  • Розширення і спеціалізація: Можна додати нові властивості й методи або змінити наявні лише там, де це потрібно. Усі тварини видають звуки, але кішка нявкає, а собака — гавкає. При цьому кішці можна додати уміння лазити по деревах (а в базовому класі такого уміння немає).
  • Структуризація ієрархій: Код стає логічнішим і зрозумілішим. Наприклад, якщо у вас є класи Animal, Dog, Cat, то одразу видно, що Dog і Cat — спеціалізації класу Animal.

Приклад. Якби в Java не було наслідування, вам довелося б копіювати методи на кшталт eat(), sleep() і поле name у кожен клас тварини. А якщо завтра знадобиться додати метод breathe(), доведеться змінювати десятки класів! Із наслідуванням достатньо додати можливість дихати до базового класу.

2. Синтаксис наслідування: extends

Як оголосити наслідування в Java? Усе дуже просто: використовуйте ключове слово extends.

class РодительскийКласс {
    // поля та методи
}

class Подкласс extends РодительскийКласс {
    // додаткові поля та методи
}

Приклад 1: Тварини

// Батьківський клас
class Animal {
    String name;

    void eat() {
        System.out.println(name + " їсть.");
    }
}

// Підклас
class Cat extends Animal {
    void meow() {
        System.out.println(name + " каже: Няв!");
    }
}

Що тут відбувається?

  • Клас Cat наслідує всі поля й методи класу Animal.
  • Отже, у Cat вже є поле name і метод eat(), хоча ми їх не писали явно.
  • Плюс у Cat з’являється власний метод meow().

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

public class Main {
    public static void main(String[] args) {
        Cat kitty = new Cat();
        kitty.name = "Барсик";
        kitty.eat();      // Барсик їсть.  (успадковано)
        kitty.meow();     // Барсик каже: Няв! (власний метод)
    }
}

Вуаля! Ми отримали новий клас із мінімумом коду, уникнувши дублювання.

3. Що саме наслідує підклас?

У Java підклас наслідує:

  • Усі відкриті (public) і захищені (protected) поля та методи базового класу.
  • Усі з доступом package-private поля та методи, якщо підклас у тому самому пакеті.

Не наслідує:

  • Конструктори (їх потрібно явно оголошувати в підкласі).
  • Приватні (private) поля та методи (вони доступні лише всередині самого базового класу).
  • Статичні блоки ініціалізації (вони не наслідуються, але в кожному класі можуть бути свої).
  • Члени з доступом package-private, якщо підклас розташований в іншому пакеті.

Ілюстрація

class Animal {
    public String name;
    private int age;

    public void eat() { 
        System.out.println("Їм"); 
    }
    private void secret() { 
        System.out.println("Таємниця!"); 
    }
}

class Dog extends Animal {
    public void bark() { 
        System.out.println("Гав!"); 
    }
}
  • Dog успадкує поле name і метод eat().
  • Dog не бачить поле age і метод secret() — вони приватні.

4. Обмеження наслідування в Java

Java — доволі сувора пані, і вона має свої правила:

Лише одиничне наслідування класів: кожен клас може наслідувати лише один інший клас. Натомість клас може мати скільки завгодно нащадків.

class Dog extends Animal { ... } // ОК
class Dog extends Animal, Pet { ... } // Помилка! Так не можна

Множинне наслідування інтерфейсів — дозволено, але це окрема історія, і ми поговоримо про це пізніше.

Клас Object — предок усіх класів у Java. Навіть якщо ви явно не пишете extends, ваш клас усе одно неявно наслідує Object.

5. Практичний приклад

Продовжмо будувати наш «зоологічний» застосунок.

Крок 1. Базовий клас Animal

class Animal {
    String name;

    void eat() {
        System.out.println(name + " їсть.");
    }
}

Крок 2. Підклас Cat

class Cat extends Animal {
    void meow() {
        System.out.println(name + " каже: Няв!");
    }
}

Крок 3. Підклас Dog

class Dog extends Animal {
    void bark() {
        System.out.println(name + " каже: Гав!");
    }
}

Крок 4. Використаємо класи

public class Main {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name = "Мурка";
        cat.eat();   // Мурка їсть.
        cat.meow();  // Мурка каже: Няв!

        Dog dog = new Dog();
        dog.name = "Шарик";
        dog.eat();   // Шарик їсть.
        dog.bark();  // Шарик каже: Гав!
    }
}

Що ми отримали?

  • Обидва класи Cat і Dog використовують спільне поле name і метод eat() із базового класу.
  • Кожен клас додає свою унікальну поведінку: meow() для кішки, bark() для собаки.
  • Якщо потрібно змінити те, як тварини їдять, достатньо змінити метод eat() у класі Animal — зміни автоматично застосуються до всіх нащадків.

6. Корисні нюанси

Візуалізація: ієрархія класів

Ієрархію можна уявити так:

.        Animal
        /    \
     Cat     Dog
  • Animal — базовий клас, містить усе спільне для тварин.
  • Cat і Dog — підкласи, додають унікальні особливості.

Трохи про конструктори й наслідування

Конструктори не наслідуються. Якщо ви не визначаєте конструктор у підкласі, Java автоматично додасть конструктор без параметрів (якщо він є у батьківському класі). Якщо батьківський клас має лише конструктор із параметрами, у підкласі його потрібно викликати явно через super(...). Короткий приклад:

class Animal {
    String name;
    Animal(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    Cat(String name) {
        super(name); // викликаємо конструктор батьківського класу
    }
}

7. Типові помилки під час використання наслідування

Помилка № 1: Спроба наслідувати одразу від кількох класів.
У Java не можна написати class Cat extends Animal, Pet. Лише один батьківський клас!

Помилка № 2: Очікування, що приватні поля та методи будуть доступні в підкласі.
Приватні члени не наслідуються (точніше, вони є, але з підкласу до них немає доступу). Використовуйте protected, якщо потрібно дозволити доступ нащадкам.

Помилка № 3: Забутий виклик конструктора батьківського класу.
Якщо в базовому класі немає конструктора без параметрів, а ви не викликаєте явно super(...), буде помилка компіляції.

Помилка № 4: Використання наслідування «заради економії коду», а не за змістом.
Якщо між класами немає відношення «є» (is-a), краще не використовувати наслідування. Наприклад, «Людина» не має наслідувати від «Автомобіля», навіть якщо в обох є поле speed.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ