Laboratorio di Sistemi Polimorfismo Java Prerequisiti: per la comprensione dell'articolo è necessario conoscere il concetto di Ereditarietà in Java. Di solito se abbiamo la struttura di una classe con gli attributi e i metodi possiamo istanziare oggetti a partire da quella classe. Esistono però classi particolari, chiamate classi astratte, che non possono dare origine a oggetti. Si usano per creare una gerarchia in cui tutte le classi discendenti devono possedere un certo metodo. In una classe astratta, almeno un metodo è soltanto definito ma non implementato. Oppure, in altre parole, se una classe possiede almeno un metodo astratto, è essa stessa astratta. Poiché il metodo non possiede il codice, qualora ne fosse richiesta la sua esecuzione, non saprebbe come comportarsi: per questo motivo non ci possono essere oggetti creati a partire dalla classe astratta. Per usare una classe astratta, occorre creare una sottoclasse (o più sottoclassi) in cui i metodi non implementati vengono ridefiniti (overridding). Nella sottosclasse per ogni metodo astratto della superclasse viene creato un nuovo metodo con lo stesso nome del metodo non implementato, stessi parametri e valore di ritorno. Quando i metodi sono stati tutti implementati, la superclasse in un certo senso non è più astratta e si possono allora generare gli oggetti (per mezzo delle sue sottoclassi). Esempio: consideriamo la seguente gerarchia: Per comodità, supponiamo che il modificatore di visibilità degli attributi della superclasse Animale sia protected (in questo modo, anche se le classi derivate appartengono a package differenti rispetto alla superclasse, gli attributi della superclasse si possono facilmente ereditare). Osserviamo la struttura dei package: polimorfismo.pdf Pag. 1/5 Cozzetto © Laboratorio di Sistemi Polimorfismo Java Segue codice delle classi: /* * Animale.java */ package classiAstratte; /** * * @author maurizio */ public abstract class Animale { protected String nome; // attributi “generali” della classe Animale protected String tipoAnimale; public Animale() { } public abstract void emettiVerso(); // metodo astratto public abstract void stampa(); // metodo astratto } // fine classe Animale polimorfismo.pdf Pag. 2/5 Cozzetto © Laboratorio di Sistemi Polimorfismo Java /* * Cane.java */ package classiConcrete; import classiAstratte.Animale; /** * * @author maurizio */ public class Cane extends Animale { // la classe Cane estende la classe Animale per includere l'attributo “razza” String razza; public Cane() { // la parola riservata super è un riferimento implicito alla superclasse super.nome="Brick"; super.tipoAnimale="cane"; razza="Mastino napoletano"; } @Override // ridefinizione del metodo emettiVerso() della superclasse astratta Animale public void emettiVerso() { System.out.println("Io faccio \"Bau bau\""); } @Override // ridefinizione del metodo toString() della classe superclasse Object public String toString() { return "Io sono un "+super.tipoAnimale+" e mi chiamo "+super.nome+" di razza "+razza; } @Override // ridefinizione del metodo stampa() della superclasse public void stampa() { System.out.println(toString()); } } // fine classe Cane polimorfismo.pdf Pag. 3/5 Cozzetto © Laboratorio di Sistemi Polimorfismo Java /* * Gatto.java */ package classiConcrete; import classiAstratte.Animale; /** * * @author maurizio */ public class Gatto extends Animale { public Gatto() { super.tipoAnimale="gatto"; super.nome="MicioMiao"; } @Override // ridefinizione del metodo emettiVerso() public void emettiVerso() { System.out.println("Io faccio \"Miao Miao\""); } @Override // ridefinizione di toString() public String toString() { return "Io sono un "+super.tipoAnimale+" e mi chiamo "+super.nome; } @Override // ridefinizione di stampa() public void stampa() { System.out.println(toString()); } } // fine classe Gatto /* * Main.java */ package main; import classiConcrete.Cane; import classiConcrete.Gatto; polimorfismo.pdf Pag. 4/5 Cozzetto © Laboratorio di Sistemi Polimorfismo Java /** * * @author maurizio */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { // istanzio un oggetto di tipo “Cane” Cane c = new Cane(); // stampo l'oggetto c.stampa(); // gli faccio emettere un suono c.emettiVerso(); // istanzio un oggetto di tipo “Gatto” Gatto g = new Gatto(); // stampo l'oggetto g.stampa(); // gli faccio emettere un verso g.emettiVerso(); } } // fine classe Main Questo semplice esempio ci introduce anche al concetto di polimorfismo (la parola deriva dal greco e possiamo tradurla con: più forme). Abbiamo due tipi di polimorfismo: il primo consiste nell'overloading di un metodo. Cioè la possibilità di usare lo stesso metodo per compiere operazioni su oggetti differenti: System.out.println(“Questa è una stringa”); // stampa di una stringa System.out.println(24); // stampa di un intero System.out.println(434.541); // stampa di un double Cioè stesso oggetto e stesso metodo ma argomenti differenti. Questo tipo di polimorfismo lo abbiamo usato spesso per fare l'overloading del costruttore. L'altro tipo di polimorfismo consiste proprio nell'overridding di un metodo. Infatti se c è un oggetto di tipo Cane e g è un oggetto di tipo Gatto, posso scrivere c.emettiVerso() e g.emettiVerso() cioè oggetti differenti ma stesso metodo (ogni animale emette un verso e ciascuno emetterà il “proprio” verso). polimorfismo.pdf Pag. 5/5 Cozzetto ©