Overloading dei Metodi con Varargs in Java
- I metodi varargs in Java possono essere sovraccaricati.
- È possibile sovraccaricare un metodo varargs utilizzando diversi tipi di parametri o aggiungendo parametri normali.
- Tuttavia, è importante prestare attenzione all'ambiguità quando si sovraccaricano i metodi varargs, poiché possono verificarsi errori di ambiguità che impediscono la compilazione del programma.
- In alcuni casi, è meglio evitare il sovraccarico e utilizzare nomi di metodi distinti per evitare ambiguità.
Metodi Varargs e Overloading
È possibile sovraccaricare un metodo che accetta un argomento a lunghezza variabile.
Ad esempio, il programma seguente sovraccarica verificaVar()
tre volte:
// Varargs e sovraccarico.
class VarArgs3 {
static void verificaVar(int ... v) {
System.out.print("verificaVar(int ...): " +
"Numero di argomenti: " + v.length +
" Contenuto: ");
for(int x : v)
System.out.print(x + " ");
System.out.println();
}
static void verificaVar(boolean ... v) {
System.out.print("verificaVar(boolean ...) " +
"Numero di argomenti: " + v.length +
" Contenuto: ");
for(boolean x : v)
System.out.print(x + " ");
System.out.println();
}
static void verificaVar(String msg, int ... v) {
System.out.print("verificaVar(String, int ...): " +
msg + v.length +
" Contenuto: ");
for(int x : v)
System.out.print(x + " ");
System.out.println();
}
public static void main(String[] args)
{
verificaVar(1, 2, 3);
verificaVar("Test: ", 10, 20);
verificaVar(true, false, false);
}
}
L'output prodotto da questo programma è mostrato di seguito:
verificaVar(int ...): Numero di argomenti: 3 Contenuto: 1 2 3
verificaVar(String, int ...): Test: 2 Contenuto: 10 20
verificaVar(boolean ...): Numero di argomenti: 3 Contenuto: true false false
Questo programma illustra entrambi i modi in cui un metodo varargs può essere sovraccaricato.
Primo, i tipi del parametro vararg possono differire. Questo è il caso di verificaVar(int ...)
e verificaVar(boolean ...)
. Ricordare, i tre punti ...
fanno sì che il parametro venga trattato come un array del tipo specificato. Pertanto, proprio come è possibile sovraccaricare metodi usando diversi tipi di parametri array, si possono sovraccaricare metodi vararg utilizzando diversi tipi di varargs. In questo caso, Java utilizza la differenza di tipo per determinare quale versione sovraccaricata del metodo chiamare.
Il secondo modo per sovraccaricare un metodo varargs è aggiungere uno o più parametri normali. Questo è ciò che è stato fatto con verificaVar(String, int ...)
. In questo caso, Java utilizza sia il numero di argomenti che il tipo degli argomenti per determinare quale metodo chiamare.
Varargs e metodi non-varargs
Un metodo varargs può anche essere sovraccaricato da un metodo non-varargs. Ad esempio, verificaVar(int x)
è un sovraccarico valido di verificaVar()
nel programma precedente. Questa versione viene invocata solo quando è presente un solo argomento int
. Quando vengono passati due o più argomenti int
, viene utilizzata la versione varargs verificaVar(int...)
.
Varargs e Ambiguità
Possono verificarsi errori alquanto inaspettati durante il sovraccarico di un metodo che accetta un argomento a lunghezza variabile.
Questi errori riguardano l'ambiguità, perché è possibile creare una chiamata ambigua a un metodo varargs sovraccaricato. Ad esempio, si consideri il seguente programma:
// Varargs, sovraccarico e ambiguità.
//
// Questo programma contiene un errore e
// non compila!
class VarArgs4 {
static void verificaVar(int ... v) {
System.out.print("verificaVar(int ...): " +
"Numero di argomenti: " + v.length +
" Contenuto: ");
for(int x : v)
System.out.print(x + " ");
System.out.println();
}
static void verificaVar(boolean ... v) {
System.out.print("verificaVar(boolean ...) " +
"Numero di argomenti: " + v.length +
" Contenuto: ");
for(boolean x : v)
System.out.print(x + " ");
System.out.println();
}
public static void main(String[] args)
{
verificaVar(1, 2, 3); // OK
verificaVar(true, false, false); // OK
verificaVar(); // Errore: Ambiguo!
}
}
Nel programma sopra, il sovraccarico di verificaVar()
è perfettamente corretto. Tuttavia, questo programma non compilerà a causa della seguente chiamata:
verificaVar(); // Errore: Ambiguo!
Poiché il parametro vararg può essere vuoto, questa chiamata potrebbe essere tradotta sia in una chiamata a verificaVar(int ...)
che a verificaVar(boolean ...)
. Entrambe sono ugualmente valide. Dunque, la chiamata è intrinsecamente ambigua.
Ecco un altro esempio di ambiguità. Le seguenti versioni sovraccaricate di verificaVar()
sono intrinsecamente ambigue anche se una di esse accetta un parametro normale:
static void verificaVar(int ... v) { // ...
}
static void verificaVar(int n, int ... v) { // ...
}
Sebbene le liste di parametri di verificaVar()
differiscano, non c'è modo per il compilatore di risolvere la seguente chiamata:
verificaVar(1)
Questa si traduce in una chiamata a verificaVar(int ...)
, con un argomento vararg, oppure in una chiamata a verificaVar(int, int ...)
senza argomenti vararg? Non c'è modo per il compilatore di rispondere a questa domanda. Dunque, la situazione è ambigua.
A causa di errori di ambiguità come quelli mostrati sopra, a volte è necessario rinunciare al sovraccarico e semplicemente usare due nomi di metodi differenti. Inoltre, in alcuni casi, l'ambiguità esprime un difetto concettuale nel codice, che può anche essere risolto progettando più accuratamente la struttura del programma.