1. Sintassi del sovraccarico dei costruttori
Nella vita reale, raramente tutti gli oggetti vengono creati allo stesso modo. Immaginate la classe Person (Persona). A volte dobbiamo creare una persona conoscendone solo il nome. A volte — nome ed età. E a volte — non sappiamo niente, quindi lasciamo tutto ai valori predefiniti. Sarebbe strano costringere l’utente della classe a specificare sempre tutti i parametri, anche quando non gli servono.
Sovraccarico dei costruttori — è un modo per dare all’utente della classe la scelta: quali parametri vuole specificare alla creazione dell’oggetto e quali lasciare ai valori predefiniti. Questo rende la classe flessibile e comoda da usare.
Analogia:
In un ufficio di progettazione si costruiscono automobili. Qualcuno ordina l’allestimento base (senza climatizzatore, solo volante e ruote), qualcuno vuole «lusso» (con sedili riscaldati, Wi‑Fi e che l’auto guidi da sola). Ma l’auto è comunque la stessa classe, semplicemente ci sono modi diversi di assemblarla!
Il sovraccarico è quando in un’unica classe sono dichiarati più costruttori, ma con parametri diversi (diverso numero, tipo o ordine dei parametri). Tutti hanno lo stesso nome della classe e non hanno tipo di ritorno.
Esempio: classe con costruttori sovraccarichi
public class Person {
String name;
int age;
// Costruttore senza parametri (predefinito)
public Person() {
this.name = "Sconosciuto";
this.age = 0;
}
// Costruttore con un parametro
public Person(String name) {
this.name = name;
this.age = 0;
}
// Costruttore con due parametri
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Ora possiamo creare oggetti in modi diversi:
Person p1 = new Person(); // nome = "Sconosciuto", età = 0
Person p2 = new Person("Vasya"); // nome = "Vasya", età = 0
Person p3 = new Person("Petya", 25); // nome = "Petya", età = 25
Come fa Java a capire quale costruttore usare?
Java guarda al numero e ai tipi degli argomenti che passate dopo new. Se scrivete new Person("Vasya"), il compilatore cerca un costruttore con un parametro di tipo String. Se scrivete new Person("Petya", 25), serve un costruttore con parametri String e int.
2. Chiamare un costruttore da un altro: this(...)
A volte, con il sovraccarico dei costruttori, si verifica una situazione in cui parte del codice si ripete. Ad esempio, volete che tutti i costruttori impostino sempre il nome e che l’età, se non specificata, sia pari a zero. Per non copiare la stessa logica in ogni costruttore, potete chiamare un costruttore da un altro con la parola chiave this(...).
Esempio
public class Person {
String name;
int age;
// Costruttore con due parametri
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Il costruttore con un parametro chiama l'altro costruttore
public Person(String name) {
this(name, 0); // chiama Person(String name, int age)
}
// Il costruttore senza parametri chiama l'altro costruttore
public Person() {
this("Sconosciuto", 0);
}
}
public Person(String name) {
this(name, 0); // chiama Person(String, int)
}
Regola importante: La chiamata a un altro costruttore tramite this(...) deve essere la prima riga del costruttore!
Perché serve?
- Riduce la duplicazione del codice.
- Se decidete di cambiare la logica di inizializzazione (ad esempio, modificare un valore predefinito), dovrete intervenire in un solo punto.
- Il codice diventa più pulito e più facile da mantenere.
3. Esempi pratici: sovraccarico in una classe reale
Supponiamo di avere la classe Account — conto bancario. A volte conosciamo solo il nome del proprietario, a volte vogliamo specificare subito il saldo iniziale e talvolta anche la valuta.
Esempio di classe con costruttori sovraccarichi
public class Account {
String owner;
double balance;
String currency;
// Costruttore con tre parametri
public Account(String owner, double balance, String currency) {
this.owner = owner;
this.balance = balance;
this.currency = currency;
}
// Costruttore con due parametri (valuta predefinita — "EUR")
public Account(String owner, double balance) {
this(owner, balance, "EUR");
}
// Costruttore con un parametro (saldo = 0, valuta = "EUR")
public Account(String owner) {
this(owner, 0.0, "EUR");
}
// Costruttore senza parametri (proprietario = "Sconosciuto", saldo = 0, valuta = "EUR")
public Account() {
this("Sconosciuto", 0.0, "EUR");
}
public void printInfo() {
System.out.println(owner + ": " + balance + " " + currency);
}
}
Uso
public class Main {
public static void main(String[] args) {
Account acc1 = new Account("Ivan", 1000, "USD");
Account acc2 = new Account("Maria", 500);
Account acc3 = new Account("Pyotr");
Account acc4 = new Account();
acc1.printInfo(); // Ivan: 1000.0 USD
acc2.printInfo(); // Maria: 500.0 EUR
acc3.printInfo(); // Pyotr: 0.0 EUR
acc4.printInfo(); // Sconosciuto: 0.0 EUR
}
}
Perché è comodo?
- Potete creare oggetti con diversi livelli di dettaglio.
- Non è necessario specificare ogni volta tutti i parametri (soprattutto se spesso sono gli stessi).
- La classe è facile da estendere: se compare un nuovo parametro, potete aggiungere un altro costruttore.
4. Errori tipici nel sovraccarico dei costruttori
Errore n. 1: Confusione con i tipi e l’ordine dei parametri.
Se avete due costruttori — Person(String name, int age) e Person(int age, String name) — il compilatore li distinguerà, ma per l’utente della classe può essere estremamente fuorviante. Meglio evitare tali situazioni.
Errore n. 2: Mancanza del costruttore predefinito.
Se dichiarate solo costruttori con parametri e poi provate a creare un oggetto senza parametri, otterrete un errore di compilazione. Aggiungete sempre un costruttore senza parametri se vi serve.
Errore n. 3: Tentare di chiamare un altro costruttore non come prima riga.
La chiamata this(...) deve sempre essere la prima riga del costruttore. Se scrivete qualcosa prima, avrete un errore di compilazione.
Errore n. 4: Ciclo di chiamate ai costruttori.
Se un costruttore chiama se stesso (direttamente o tramite una catena), ciò porterà a un errore di compilazione a causa della ricorsione infinita.
Errore n. 5: Campi non inizializzati.
Se vi dimenticate di inizializzare un qualche campo nel costruttore (o nella catena di chiamate), l’oggetto può trovarsi in uno stato non valido. Verificate che tutti i campi abbiano valori significativi dopo la creazione dell’oggetto.
GO TO FULL VERSION