Nella lezione dedicata ai costruttori di una classe abbiamo detto che i costruttori altro non sono che dei metodi speciali che vengono richiamati ogni qualvolta viene effettuata l’istanza di una classe. Dato che comunque appartengono alla famiglia dei metodi sarà possibile utilizzare le tecniche di overload ed override?
L’overload di un costruttore è possibile ed è un metodo molto potente che ci permette di costruire oggetti di una stessa classe che risultano però 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 dunque, usando la solita sintassi, creeremo l’oggetto. Se per esempio, di un fornitore non abbiamo il numero di telefono, non potremo creare l’istanza della classe perchè il costruttore necessariamente prende in ingresso quattro parametri. A questo punto è possibile utilizzare l’overload dei costruttore 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 di un costruttore, invece, non è una tecnica utilizzabile in quanto quando estendiamo una classe i costruttori presenti in una classe non vengono ereditati, dunque non è possibile effettuare una riscrittura del costruttore. Questa potrebbe risultare una limitazione del Java, ma analizzando attentamente tutti gli aspetti vedremo che il fatto di non ereditare un costruttore non limita le potenzialità del linguaggio.
Iniziamo con il dire che il costruttore di una qualunque classe, come prima istruzione richiama il costruttore della superclasse a cui fa riferimento. Per esempio se istanziamo un oggetto di tipo "ResponsabileDiProgetto", il costruttore chiamerà automaticamente il costruttore della superclasse relativa, ovvero richiamerà il costruttore della classe "Dipendente" (se non è presente nessun costruttore viene richiamo il costruttore di dafault). Sottolineiamo che la chiamata al costruttore della superclasse, in java, è una cosa inevitabile. Vediamo però come può essere gestita questa apparente limitazione utilizzando il reference super(). Con il reference super è possibile accedere ad attributi o metodi della superclasse che abbiamo ereditato e quindi anche al costruttore della superclasse. Facciamo un esempio esplicativo: riprendiamo le classi di esempio "Dipendent"e e "ResponsabileDiProgetto". Con il reference super() è possibile, nella classe ereditata, accedere al costruttore della classe "Dipendente" senza dover riscrivere il codice. La classe "Dipendente", con il 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=g;
oreLavorativeMensili=o;
retribuzioneOraria=r;
}
}
A questo punto, sfruttando il referennce super() la classe "ResponsabileDiProgetto" sarà dunque la seguente:
public class ResponsabileDiProgetto {
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" magari mettendo alcune limitazioni sulle ore lavorative mensili, alla classe "ResponsabileDiProgetto" non dovremo apportare nessuna modifica, dato che con la chiamata a super() richiameremo il costruttore, modificato, della superclasse "Dipendente".
Inoltre il refernce super() ci ha permesso di evitare di ricopiare il codice presente nel costruttore della classe dipendente per l’assegnazione degli attributi nome, cognome ecc. Oltre ad aver avuto un netto vantaggio dal punto di vista temporale, avremo un codice che può essere modificato con un’estrema semplicità dato che deve essere modificato solo il codice della superclasse.
Senza super() se immaginiamo di avere venti classi ereditate da una superclasse ed ad un certo punto dover modificare il codice per i costruttori dovremo andare a mettere le mani su venti classi differenti aumentando in maniera esponenziale la possibilità di commettere errori e creare bugs difficilmente rilevabili.