JavaRush /Курси /JAVA 25 SELF /Перевантаження конструкторів

Перевантаження конструкторів

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

1. Синтаксис перевантаження конструкторів

У житті рідко буває так, щоб усі обʼєкти створювалися однаково. Уявіть клас Person (Людина). Інколи потрібно створити людину, знаючи лише її імʼя. Іноді — імʼя та вік. А буває, що взагалі нічого не відомо — нехай усе буде за замовчуванням. Було б дивно змушувати користувача класу завжди вказувати всі параметри, навіть якщо вони йому не потрібні.

Перевантаження конструкторів — це спосіб надати користувачеві класу вибір: які параметри він хоче вказати під час створення обʼєкта, а які залишити за замовчуванням. Це робить клас гнучким і зручним у використанні.

Аналогія:
У конструкторському бюро будують автомобілі. Хтось замовляє базову комплектацію (без кондиціонера, лише кермо й колеса), хтось хоче «люкс» (з підігрівом сидінь, Wi‑Fi й щоб машина сама їхала). Але машина — це все одно один і той самий клас, просто різні способи її зібрати!

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

Приклад: клас із перевантаженими конструкторами

public class Person {
    String name;
    int age;

    // Конструктор без параметрів (за замовчуванням)
    public Person() {
        this.name = "Невідомо";
        this.age = 0;
    }

    // Конструктор з одним параметром
    public Person(String name) {
        this.name = name;
        this.age = 0;
    }

    // Конструктор з двома параметрами
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Тепер ми можемо створювати обʼєкти різними способами:

Person p1 = new Person();                // імʼя = "Невідомо", вік = 0
Person p2 = new Person("Василь");        // імʼя = "Василь", вік = 0
Person p3 = new Person("Петро", 25);     // імʼя = "Петро", вік = 25

Як Java визначає, який конструктор використати?

Java обирає його за кількістю та типами аргументів, які ви передаєте після new. Якщо ви пишете new Person("Василь"), компілятор шукає конструктор з одним параметром типу String. Якщо ви пишете new Person("Петро", 25), потрібен конструктор з параметрами String і int.

2. Виклик одного конструктора з іншого: this(...)

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

Приклад

public class Person {
    String name;
    int age;

    // Конструктор з двома параметрами
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Конструктор з одним параметром викликає інший конструктор
    public Person(String name) {
        this(name, 0); // викликає Person(String name, int age)
    }

    // Конструктор без параметрів викликає інший конструктор
    public Person() {
        this("Невідомо", 0);
    }
}
public Person(String name) {
    this(name, 0); // викликає Person(String, int)
}
Виклик одного конструктора з іншого через this(...)

Важливе правило: Виклик іншого конструктора через this(...) має бути першим рядком конструктора!

Навіщо це потрібно?

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

3. Практичні приклади: перевантаження в реальному класі

Нехай у нас є клас Account — банківський рахунок. Буває, знаємо лише імʼя власника, інколи хочемо одразу вказати початковий баланс, а іноді — ще й валюту.

Приклад класу з перевантаженими конструкторами

public class Account {
    String owner;
    double balance;
    String currency;

    // Конструктор з трьома параметрами
    public Account(String owner, double balance, String currency) {
        this.owner = owner;
        this.balance = balance;
        this.currency = currency;
    }

    // Конструктор з двома параметрами (валюта за замовчуванням — "EUR")
    public Account(String owner, double balance) {
        this(owner, balance, "EUR");
    }

    // Конструктор з одним параметром (баланс = 0, валюта = "EUR")
    public Account(String owner) {
        this(owner, 0.0, "EUR");
    }

    // Конструктор без параметрів (власник — "Невідомо", баланс = 0, валюта = "EUR")
    public Account() {
        this("Невідомо", 0.0, "EUR");
    }

    public void printInfo() {
        System.out.println(owner + ": " + balance + " " + currency);
    }
}

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

public class Main {
    public static void main(String[] args) {
        Account acc1 = new Account("Іван", 1000, "USD");
        Account acc2 = new Account("Марія", 500);
        Account acc3 = new Account("Петро");
        Account acc4 = new Account();

        acc1.printInfo(); // Іван: 1000.0 USD
        acc2.printInfo(); // Марія: 500.0 EUR
        acc3.printInfo(); // Петро: 0.0 EUR
        acc4.printInfo(); // Невідомо: 0.0 EUR
    }
}

Чому це зручно?

  • Можна створювати обʼєкти з різним рівнем деталізації.
  • Не потрібно щоразу вказувати всі параметри (особливо якщо вони часто однакові).
  • Легко розширювати клас: якщо зʼявиться новий параметр, можна додати ще один конструктор.

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

Помилка № 1: Плутанина з типами й порядком параметрів.
Якщо у вас є два конструктори — Person(String name, int age) і Person(int age, String name) — компілятор їх розрізнить, але для користувача класу це може бути вкрай заплутано. Краще уникати таких ситуацій.

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

Помилка № 3: Спроба викликати інший конструктор не першим рядком.
Виклик this(...) завжди має бути першим рядком конструктора. Якщо написати щось перед цим — буде помилка компіляції.

Помилка № 4: Зациклення викликів конструкторів.
Якщо конструктор викликає сам себе (напряму або через ланцюжок), це призведе до помилки компіляції через нескінченну рекурсію.

Помилка № 5: Неініціалізовані поля.
Якщо забули ініціалізувати якесь поле в конструкторі (або в ланцюжку викликів), обʼєкт може опинитися в некоректному стані. Перевіряйте, щоб усі поля мали змістовні значення після створення обʼєкта.

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