Bentrovati! La scorsa settimana abbiamo messo a cuocere la nostra prima classe Java: un Impiegato con nome, stipendio e dataAssunzione. Dopo sette giorni, ora che l’Impiegato sarà ben cotto e tenero, possiamo ripartire e cominciare a vedere insieme come si realizza in Java l’ereditarietà.
Ereditare da un impiegato
Allora, innanzitutto dobbiamo contattare un bravo notaio…no, scusate: stiamo parlando della ereditarietà di cui parlavamo nel nostro post sull’UML, una relazione in cui un’entità è un tipo specifico di un’altra (is-a relationship), ereditandone proprietà e metodi e aggiungendone di propri.
Ad esempio: un Manager è un tipo specifico di Impiegato perché ha tutti i suoi attributi, ma in più aggiunge l’attributo premioProduzione, inteso come bonus annuale relativo alla produttività straordinaria. Come scriviamo questo in Java? Ripartiamo per comodità dalla definizione di Impiegato:
public class Impiegato { protected String nome; protected double stipendio; protected Date dataAssunzione; public Impiegato(String n, double s, Date d) { nome = n; stipendio = s; dataAssunzione = d; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public double getStipendio() { return stipendio; } public void setStipendio(double stipendio) { this.stipendio = stipendio; } public Date getDataAssunzione() { return dataAssunzione; } public void setDataAssunzione(Date dataAssunzione) { this.dataAssunzione = dataAssunzione; } } |
I più attenti di voi noteranno che ci sono delle piccole differenze (forse dovute alla cottura?): i field non hanno più visibilità private, ma protected! Quando un field è dichiarato private non è accessibile se non dentro al codice della classe stessa; quando è protected è accessibile anche dalle classi che la estendono: per questo motivo protected è utilizzato di frequente al posto di private nelle classi “padri” in una gerarchia di ereditarietà.
Un figlio Manager?
Scriviamo ora la nostra classe Manager:
public class Manager extends Impiegato { private double premioProduzione; public Manager(String n, double s, Date d) { super(n, s, d); } public double getPremioProduzione() { return premioProduzione; } public void setPremioProduzione(double premioProduzione) { this.premioProduzione = premioProduzione; } } |
La parola chiave usata in Java per indicare che una classe ne estende un’altra (eredita, è figlia, è un sottotipo, è in relazione di ereditarietà e così via) è extends. Istanziando un oggetto di tipo Manager abbiamo a disposizione tutte le proprietà della classe Impiegato senza riscriverle (non male, no?) e in più abbiamo il nuovo attributo specifico: premioProduzione.
Notiamo il costruttore: fa capolino una nuova parola chiave del linguaggio Java: super. Essa indica la classe padre, quella da cui si estende; seguita da parentesi individua il suo costruttore: stiamo dicendo che per costruire un oggetto di tipo Manager rimandiamo al costruttore di Impiegato. Questo perché non abbiamo considerato la nuova proprietà, specifica di Manager. Nulla ci vieta comunque di aggiungere un nuovo costruttore che prende in considerazione anche premioProduzione e che in parte rimanda al costruttore di Impiegato per inizializzare:
public Manager(String n, double s, Date d, double pp) { super(n, s, d); premioProduzione = pp; } |
Metodo, perfavore!
La scorsa volta abbiamo promesso che avremo anche mostrato un metodo di esempio: non si vive di soli attributi!. Infatti nell’OOP (e quindi anche in Java) un tipo è autoconsistente, ovvero contiene le sue proprietà, ma anche le operazioni di cui è responsabile.
Aggiungiamo alla classe Manager il metodo calcolaPercentuale, che calcola la percentuale del reddito netto annuo corrisponde al premio di produzione, ipotizzando 13 mensilità da contratto:
public int calcolaPercentuale() { return (int) Math.round((premioProduzione / (stipendio * 13)) * 100); } |
Il metodo è dichiarato public, può pertando essere invocato da chiunque. Non ha parametri in ingresso e restituisce un intero (arrotondando il risultato della divisione che esegue).
All’interno del metodo calcolaPercentuale della classe Manager ho potuto usare tranquillamente stipendio, grazie al fatto che l’ho dichiarato protected; in caso contrario avrei dovuto usare il suo getter, cosa non usuale perché l’utilizzo di field protected è ideale in questi casi: garantisce sicurezza e comodità a chi estende una classe con una relazione di ereditarietà.
Facciamo fare qualcosa a questi Manager!
E’ ora di usare un’istanza di tipo Manager in un bel main:
public class ManagerTest { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); calendar.set(2004, 8, 29); Manager topManager = new Manager("Goffredo", 1237.25, calendar.getTime(), 5240.55); System.out .println("La percentuale sul reddito netto annuo del premio di produzione è stata: " + topManager.calcolaPercentuale() + "%"); } } |
Conclusioni
Ci siamo ulteriormente addentrati nel mondo della programmazione OOP. Adesso che abbiamo avuto modo di utilizzare l’ereditarietà mettendo mano al codice penso che sia risultata meno fumosa e che i potenziali vantaggi che ne derivano siano più evidenti. Se così non fosse non vi preoccupate: avremo modo di rivedere questi stessi concetti e di estenderli (!) in cicli iterativi nei prossimi post. Nel prossimo, in particolare, vedremo altre feature OOP del linguaggio Java leggermente più avanzate: l’overloading, l’overriding e il polimorfismo.
Alla prossima!
