Il polimorfismo e lโuso dei costruttori in Java sono concetti fondamentali per comprendere la programmazione orientata agli oggetti. In questo articolo approfondiremo entrambe le tematiche, chiarendo il loro ruolo e la loro importanza nello sviluppo di applicazioni Java.
Cosa sono i costruttori in Java?
Nella lezione dedicata ai costruttori di una classe, abbiamo detto che i costruttori sono metodi speciali che vengono richiamati ogni qualvolta si crea unโistanza di una classe. Essi non hanno un tipo di ritorno, nemmeno void, e portano il nome della classe stessa. Dato che appartengono alla famiglia dei metodi, sarร possibile utilizzare le tecniche di overload e override.
LโOverload dei Costruttori
Lโoverload di un costruttore รจ possibile ed รจ una tecnica molto potente che consente di creare oggetti di una stessa classe con parametri diversi. Immaginiamo di avere una classe Fornitore contenente gli attributi nome della ditta, partita IVA, telefono e fax:
public class Fornitore {
private String nome;
private String partitaIva;
private int telefono;
private int fax;
public Fornitore(String n, String p, int t, int f) {
nome = n;
partitaIva = p;
telefono = t;
fax = f;
}
}
Nella classe di implementazione, utilizzando la sintassi appropriata, creeremo lโoggetto. Se ad esempio, di un fornitore non abbiamo il numero di telefono, non potremo creare unโistanza della classe poichรฉ il costruttore richiede necessariamente quattro parametri. Possiamo quindi utilizzare lโoverload dei costruttori per risolvere il problema, inserendo nella classe Fornitore un altro costruttore del tipo:
public Fornitore(String n, String p, int f) {
nome = n;
partitaIva = p;
fax = f;
}
LโOverride dei Costruttori
Lโoverride di un costruttore, invece, non รจ una tecnica applicabile perchรฉ quando estendiamo una classe i costruttori presenti in una classe non vengono ereditati; di conseguenza, non รจ possibile riscrivere un costruttore. Questa potrebbe sembrare una limitazione di Java, ma analizzando attentamente i vari aspetti, vedremo che il fatto che i costruttori non siano ereditati non limita le potenzialitร del linguaggio.
Utilizzo di super() con i Costruttori
Il costruttore di una classe, come prima istruzione, richiama il costruttore della superclasse a cui fa riferimento. Ad esempio, se istanziamo un oggetto di tipo ResponsabileDiProgetto, il costruttore chiamerร automaticamente il costruttore della sua superclasse, Dipendente; se non รจ presente nessun costruttore, verrร richiamato il costruttore di default. Sottolineiamo che la chiamata al costruttore della superclasse, in Java, รจ unโoperazione inevitabile.
Possiamo gestire questa apparente limitazione utilizzando il reference super(). Con il reference super() รจ possibile accedere ad attributi o metodi della superclasse e, quindi, anche al costruttore della superclasse. Vediamo un esempio pratico: riprendiamo le classi di esempio Dipendente e ResponsabileDiProgetto. La classe Dipendente, con il suo costruttore, si presenterร cosรฌ:
public class Dipendente {
private String nome;
private String cognome;
private int oreLavorativeMensili;
private int retribuzioneOraria;
public Dipendente(String n, String c, int o, int r) {
nome = n;
cognome = c;
oreLavorativeMensili = o;
retribuzioneOraria = r;
}
}
A questo punto, sfruttando il reference super(), la classe ResponsabileDiProgetto sarร la seguente:
public class ResponsabileDiProgetto extends Dipendente {
private int bonus;
public ResponsabileDiProgetto(String n, String c, int o, int r, int b) {
super(n, c, o, r);
bonus = b;
}
}
In questo modo, nel caso in cui dovessimo modificare il costruttore della classe Dipendente, ad esempio introducendo alcune limitazioni sulle ore lavorative mensili, non sarร necessario apportare modifiche alla classe ResponsabileDiProgetto, poichรฉ con la chiamata a super() richiameremo il costruttore modificato della superclasse Dipendente.
Inoltre, lโutilizzo di super() ci ha permesso di evitare di duplicare il codice presente nel costruttore della classe Dipendente per lโassegnazione degli attributi nome, cognome, ecc. Questo non solo ci consente di risparmiare tempo, ma rende anche il nostro codice piรน manutenibile, poichรฉ eventuali modifiche dovranno essere effettuate solo nella superclasse. Senza lโuso di super(), se avessimo venti classi derivate da una superclasse e dovessimo cambiare il codice per i costruttori, dovremmo intervenire su tutte e venti le classi, creando cosรฌ maggiori possibilitร di errore e bug difficilmente rilevabili.