1. Sovraccarico dei metodi
Il sovraccarico dei metodi (method overloading) è la possibilità di dichiarare in una stessa classe più metodi con lo stesso nome ma con liste di parametri diverse (tipi, quantità o ordine degli argomenti). Quando chiami un tale metodo, il compilatore decide automaticamente quale versione usare in base agli argomenti passati.
Analogia dalla vita reale
Immagina di chiamare l’assistenza clienti di una banca. Puoi chiamare numeri diversi — per privati, per aziende, per clienti VIP. I numeri sono diversi, ma lo scopo è lo stesso — ottenere assistenza. In programmazione il sovraccarico dei metodi è come un unico numero di supporto che ti collega automaticamente all’operatore giusto a seconda della tua richiesta (ovvero dei parametri che hai passato).
Sintassi del sovraccarico in Java
In Java il sovraccarico dei metodi si realizza in modo molto semplice: dichiari più metodi con lo stesso nome ma con parametri diversi.
Regola importante:
Il sovraccarico si distingue solo per la lista dei parametri (tipo, quantità, ordine).
Non è consentito sovraccaricare solo in base al tipo di ritorno!
Il compilatore non saprà distinguere i metodi se hanno lo stesso nome e gli stessi parametri, anche se il tipo di ritorno è diverso.
Esempio semplice
public class Printer {
// Stampa di un numero intero
void print(int x) {
System.out.println("int: " + x);
}
// Stampa di una stringa
void print(String s) {
System.out.println("String: " + s);
}
// Stampa di due numeri
void print(int x, int y) {
System.out.println("int, int: " + x + ", " + y);
}
}
Utilizzo:
Printer printer = new Printer();
printer.print(42); // chiamerà print(int x)
printer.print("Hello!"); // chiamerà print(String s)
printer.print(5, 10); // chiamerà print(int x, int y)
Il compilatore determina da solo quale metodo chiamare, in base agli argomenti passati.
2. Come il compilatore sceglie il metodo giusto
Quando chiami un metodo sovraccaricato, il compilatore analizza la lista degli argomenti e cerca la versione più adatta.
Criteri di scelta:
- Corrispondenza per numero di argomenti.
- Corrispondenza per tipo di ciascun argomento (o possibilità di convertire il tipo, ad esempio, int → double).
- Se sono adatti più metodi, viene scelto il più specifico.
Esempio:
public class OverloadDemo {
void show(int x) {
System.out.println("show(int): " + x);
}
void show(double x) {
System.out.println("show(double): " + x);
}
public static void main(String[] args) {
OverloadDemo demo = new OverloadDemo();
demo.show(5); // show(int): 5
demo.show(5.5); // show(double): 5.5
}
}
Se chiami demo.show(5), il compilatore sceglierà show(int). Se lo chiami con 5.5 — sceglierà show(double).
Conversioni di tipo
Se non esiste un metodo adatto, il compilatore cercherà di convertire i tipi degli argomenti (ad esempio, int → double), ma solo se ciò è possibile e non ambiguo.
void print(double x) { /* ... */ }
print(5); // l'int 5 viene convertito in double 5.0
Sovraccaricare solo per tipo di ritorno — non funziona!
Molti principianti provano a fare così:
// Errore! Un tale sovraccarico non è possibile
int sum(int x, int y) { return x + y; }
double sum(int x, int y) { return (double) (x + y); }
Il compilatore non capirà quale metodo vuoi chiamare se scrivi semplicemente sum(2, 3).
Ricorda: il sovraccarico dei metodi è possibile solo in base ai parametri, non al tipo di ritorno!
3. Sovraccarico dei costruttori
Si possono sovraccaricare non solo i metodi normali, ma anche i costruttori!
public class Person {
String name;
int age;
// Costruttore solo con nome
public Person(String name) {
this.name = name;
this.age = 0; // predefinito
}
// Costruttore con nome ed età
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Utilizzo:
Person p1 = new Person("Anna");
Person p2 = new Person("Boris", 25);
4. Esempi pratici
Calculator con metodi sovraccaricati
Scriviamo una classe Calculator che sappia sommare numeri di tipo e quantità diversi.
public class Calculator {
// Somma di due interi
int add(int a, int b) {
return a + b;
}
// Somma di tre interi
int add(int a, int b, int c) {
return a + b + c;
}
// Somma di due double
double add(double a, double b) {
return a + b;
}
}
Utilizzo:
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 5
System.out.println(calc.add(1, 2, 3)); // 6
System.out.println(calc.add(2.5, 3.1)); // 5.6
Sovraccarico dei metodi nella libreria standard
Hai già incontrato il sovraccarico, anche se forse non te ne sei accorto. Ad esempio, il metodo println in System.out è sovraccaricato per tipi diversi:
System.out.println("Hello"); // println(String)
System.out.println(123); // println(int)
System.out.println(3.14); // println(double)
System.out.println(true); // println(boolean)
Apri i sorgenti della classe PrintStream — vedrai decine di versioni sovraccaricate di println.
5. Quando usare il sovraccarico
Il sovraccarico dei metodi è uno strumento potente, ma va usato con criterio. È utile quando:
- La logica del metodo è la stessa, ma i parametri possono differire.
- Vuoi rendere l’API della classe più amichevole e flessibile.
- Devi supportare varianti vecchie e nuove della chiamata del metodo.
Esempio dalla vita reale:
Nella nostra app didattica (ad esempio, in un task manager) si può realizzare un metodo per aggiungere un’attività con parametri diversi:
public class TaskManager {
void addTask(String description) { ... }
void addTask(String description, int priority) { ... }
void addTask(String description, int priority, String deadline) { ... }
}
Un approccio del genere non è solo comodo per chi usa il codice, ma rende anche la tua classe flessibile per futuri cambiamenti.
6. Sovraccarico e varargs (numero variabile di argomenti)
In Java è possibile dichiarare un metodo con un numero variabile di parametri tramite ... (varargs):
void printAll(String... messages) {
for (String msg : messages) {
System.out.println(msg);
}
}
Ora puoi chiamare:
printAll("Hello");
printAll("One", "Two", "Three");
Si può fare anche il sovraccarico con i varargs, ma fai attenzione: se ci sono due metodi, uno con varargs e l’altro con un numero fisso di parametri, il compilatore proverà prima a trovare una corrispondenza esatta.
7. Errori tipici nel sovraccarico dei metodi
Errore n. 1: Confusione con i tipi degli argomenti.
Se hai i metodi void process(int x) e void process(double x), la chiamata process(5) invocherà la prima versione, mentre process(5.0) — la seconda. Ma se chiami process(5L), il compilatore cercherà la corrispondenza migliore e potrebbe scegliere un sovraccarico non ovvio (o addirittura segnalare un’ambiguità).
Errore n. 2: Sovraccarico con conversione automatica.
Se hai void foo(Integer x) e void foo(Long x), la chiamata foo(5) porterà a un errore di compilazione — il compilatore non sa quale metodo scegliere, perché 5 può essere convertito sia in Integer sia in Long.
Errore n. 3: Sovraccaricare solo per tipo di ritorno.
Come già detto sopra, metodi che differiscono solo per il tipo di ritorno non possono essere sovraccaricati.
Errore n. 4: Sovraccarico ed ereditarietà.
Se in una classe base è dichiarato un metodo e in una sottoclasse dichiari un metodo con lo stesso nome ma con una firma diversa, si tratta di sovraccarico e non di overriding. Questo spesso crea confusione! Maggiori dettagli nella prossima lezione.
GO TO FULL VERSION