Ereditarietà e polimorfismo - LACAM
Transcript
Ereditarietà e polimorfismo - LACAM
Concetti di OOP OOP = Object Oriented Programming OOPS = Object Oriented Mistakes Corso di Programmazione CdS: Informatica e Tecnologie per la Produzione di Software Nicola Fanizzi [email protected] Introduzione: Concetti OOP Oggetti e Classi Information Hiding già incontrati accesso public e private Ereditarietà classi e istanziazione estendere le classi: gerarchia ereditarietà multipla: le interfacce accesso protected Polimorfismo late-binding Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 2 Ereditarietà Possibilità di definire nuove classi utilizzando come punto di partenza classi pre-esistenti L'ereditarietà organizza astrazioni di oggetti dai più generici ai più specifici L'ereditarietà stabilisce una relazione "è un" Esempi: Una mountain bike è un tipo di bicicletta Un'utilitaria è un tipo di automobile Un'automobile è un tipo di veicolo Un portatile è un tipo di computer Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 3 Gerarchia degli Strumenti Musicali Strumenti Musicali Idiofoni Membranofoni Aerofoni Ad Ancia A Canna A Bocchino Cordofoni Elettrofoni Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Clarinetto Sassofono Fagotto 4 Gerarchia 5 Strumenti Musicali La gerarchia aiuta a comprendere le relazioni e le somiglianze tra gli strumenti musicali Un clarinetto “è un” tipo di strumento a fiato Gli strumenti a fiato “sono un” tipo di aerofono NB: La relazione è un è transitiva Un clarinetto è un tipo di strumento a fiato Uno strumento a fiato è un tipo di aerofono Un clarinetto è un tipo di aerofono Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Estensione: Terminologia 6 Estensione (o derivazione) di classi definizione di una classe a partire da un’altra classe mediante l’aggiunta e/o la specializzazione di caratteristiche (attributi e/o comportamenti) classe base detta anche super-classe classe estesa detta anche derivata ovvero sotto-classe Clarinetto Strumento ad ancia Aerofono Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Strumento musicale Estensione In Java si utilizza la parola chiave extends nell’intestazione della classe derivata NB: non è constentito estendere più di una classe public class Clarinetto extends StrumentoAdAncia {...} Un oggetto di una sottoclasse, quindi, ha più tipi: per dichiarazione, è del tipo della sottoclasse è un oggetto specializzato del tipo della superclasse Clarinetto cl1 = new Clarinetto(); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 7 Classe Persona 1. 2. 3. class Persona { private String nome; private String cognome; 4. 5. 6. 7. public Persona(String nome, String cognome) { this.nome = nome; this.cognome = cognome; } 8. 9. public String getNome() { return nome; } 10. 11. public String getCognome() { return cognome; } 12. public String toString() { 14. return getNome() + “ ” + getCognome() + "."; 15. } 16. } // classe Persona 13. Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 8 Classe Studente 1. 2. class Studente extends Persona { private int matricola; 3. 4. 5. 6. 8. public Studente(String n, String c, int m) { super(n, c); this.matricola = m; } public String getMatricola() { return matricola;} public String toString() { 11. return getNome() + "" + getCognome() + ", matr. " + matricola + "."; 12. } 13. } // classe Studente 10. Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 9 Uso di Classi Derivate 1. 2. Persona p1; Studente s3; 3. 4. 5. 6. 7. 8. p1 = new Persona("Guglielmo", "Cancelli"); System.out.println(p1.getNome()); // Guglielmo System.out.println(p1.toString()); // Guglielmo Cancelli. 9. 10. s3 = new Studente("Marisa", "Monte", 123456); 11. System.out.println(s3.getCognome()); 12. // Monte 13. System.out.println(s3.getMatricola()); 14. // 123456 15. System.out.println(s3.toString()); 16. // Marisa Monte, matr. 123456. Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 10 Classi Persona e Studente Persona nome : String cognome : String p1 : Persona Persona(String n, String c) nome = "Guglielmo" cognome = "Cancelli" String getNome() String getCognome() String toString() String getNome() String getCognome() String toString() estende s3 : Studente Studente matricola : int Studente(String n, String c, int m) String getMatricola() String toString() nome = "Marisa" cognome = "Monte" matricola = "123456" String String String String getNome() getCognome() getmatricola() toString() Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 11 Ereditarietà: Costruttori 12 Quando viene costruito un nuovo oggetto sottoclasse, viene sempre chiamato il costruttore per la superclasse L'invocazione del costruttore della superclasse può essere: implicita chiamato del costruttore di default della classe base esplicita chiamata di super() all'inizio del costruttore della classe derivata Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Ereditarietà: Costruttori public class B { public B() { System.out.println("B1"); } public B(int i) { System.out.println("B2"); } } // classe B public class C extends B { public C() { System.out.println("C1"); System.out.println(); } // segue... 13 //... public C(int a) { System.out.println("C1"); System.out.println(); } public C(int a, int b) { super(a + b); System.out.println("C2"); System.out.println(); B1 } C1 public static void main (String[] args) { C o1 = new C(); C o2 = new C(2); C o3 = new C(2,4); } // & N.Fanizzi classe C Corso di Programmazione (IPSW) © 2004}S.Ferilli - dib - UniBA B1 C2 B2 C2 Accesso protected Nella definizione di gerarchie di classi, l’uso dei soli modificatori public e private è troppo restrittivo viene di solito usato il modificatore protected livello di restrizione dell’accesso intermedio tra public e private Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 14 Accesso package Un'istruzione package indica che le definizioni successive fanno parte di una collezione più vasta, detta pacchetto Classi (ed interfacce) vanno messe in un pacchetto 15 per motivi organizzativi (modularità) per motivi di accesso Per evitare conflitti sui nomi, Java inserisce le classi di un pacchetto in uno spazio di nomi (name space) separato e distinto (per ogni pacchetto). Specifica predefinita: ai membri di una classe senza specifica di accesso possono accedere solo i membri del pacchetto due classi dello stesso pacchetto hanno implicitamente accesso public e protected Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Diritti di Accesso restrizione per i membri this sottoclasse pacchetto generale public protected default private Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 16 Controllo dell'Accesso 17 Esempio 1 package demo; public class P { private int data; public P() { setData(0); } public int getData() { return data; } protected void setData (int v) { data = v; } void print() { System.out.println(); } } // class P Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Controllo dell'Accesso 18 Esempio 2 import demo.P; public class Q extends P { public Q() { super(); } public Q(int v) { setData(v); } public String toString(){ int v = getData(); return String.valueOf(v); } public void invalid1() { data = 12; } public void invalid2() { print(); } } // class Q Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Controllo dell'Accesso 19 Esempio 3 package demo; public class R { private P p; public R() { p = new P(); } public void set(int v) { p.setData(v); } public int get() { return p.getData(); } public void use() { p.print(); } public void invalid() { p.data = 12; } } //R Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Controllo dell'Accesso 20 Esempio 4 import demo.P; public class S { private P p; public void illegal1 (int v) { p.setData(v); } public S() { p = new P(); } public void illegal2 () { p.data = 12; } public int get() { return p.getData(); } public void illegal3 () { p.print(); } } // S Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Attributi ed Ereditarietà 21 Un attributo/metodo di una superclasse può essere nascosto dalla definizione nella sottoclasse di un attributo/metodo con lo stesso nome Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Attributi ed Ereditarietà public class D { protected int d; public D() { d = 0; } public D(int v) { d = v; } public void printD() { System.out.println("in D, d = " + d); System.out.println(); } } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 22 Attributi ed Ereditarietà La classe F estende D e introduce una nuova variabile istanza d. La definizione di d in F nasconde la definizione eseguita da D public class F extends D { int d; public F(int v) { d = v; super.d = v*100; } public void printF() { System.out.println("in System.out.println("in System.out.println(); } 23 D, F, d d = = " " + + super.d); this.d); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Operatore instanceof 1. 2. 4. 5. Persona p; Studente s; p = new Persona("Antonio", "Stornaiolo"); s = new Studente("Emilio", "Solfrizzi", 543210); System.out.println(p 8. // true 9. System.out.println(p 10. // false 11. System.out.println(s 12. // true 13. System.out.println(s 14. // true 7. 24 instanceof Persona); instanceof Studente); instanceof Persona); instanceof Studente); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Ereditarietà e Tipi public class X { public X() { // corpo non necessario } public static boolean isX(Object v) { return (v instanceof X); } 25 public class Y extends X { public Y() { // corpo non necessario } public static boolean isY (Object v) { return (v instanceof Y); } // continua... public static boolean isObj(X v) { return (v instanceof Object); } } // X Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Ereditarietà e Tipi public static void main(String[] args) { X x = new X(); Y y = new Y(); X z = y; System.out.println("x is an Object: " + X.isObj(x)); System.out.println("x is an X: " + X.isX (x)); System.out.println("x is a Y: " + Y.isY(x)); 26 System.out.println("y is an Object: " + X.isObj(y)); System.out.println("y is an X: " + X.isX (y)); System.out.println("y is a Y: " + Y.isY(y)); System.out.println("z is an Object: " + X.isObj(z)); System.out.println("z is an X: " + X.isX (z)); System.out.println("z is a Y: " + Y.isY(z)); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Ereditarietà e Tipi Output del programma: x x x y y y z z z is is is is is is is is is an Object: an X: true a Y: false an Object: an X: true a Y: true an Object: an X: true a Y: true true true true Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 27 Finalizzazione di Classi 28 Una classe final è una classe che non può essere estesa Gli sviluppatori potrebbero voler impedire agli utenti di estendere certe classi Rende più difficile l'intromissione mediante sovrascrittura (overriding) final public class U { // U(): costruttore predefinito public U() { } // f(): facilitatore public void f() { System.out.println("f() non può essere sovrascritto: U e' finale"); } } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Finalizzazione di Metodi 29 Un metodo final è un metodo che non può essere sovrascritto public class V { public V() { } final public void f() { System.out.println("il metodo finale f () non può essere sovrascritto"); } } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Ereditarietà e Polimorfismo 30 Polimorfismo letteralmente: da molte forme un oggetto di una classe viene considerato secondo varie sfaccettature p. di tipo statico e p. di tipo dinamico (late binding) in pratica è possibile assegnare il riferimento a un oggetto della classe estesa a una variabile il cui tipo è la classe base Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Polimorfismo Un'espressione di codice può invocare metodi diversi a seconda dei tipi di oggetti manipolati Esempio: overloading della funzione come il metodo min() di java.lang.Math Il metodo invocato dipende dai tipi di argomenti effettivi int a, b, c; double x, y, z; … c = min(a, b); z = min(x, y); // invoca min() su interi // invoca min() su double Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 31 Polimorfismo 32 Due tipi di polimorfismo Polimorfismo sintattico: determinare quale metodo invocare in fase di compilazione Efficiente Facile da comprendere e analizzare Detto anche polimorfismo primitivo Polimorfismo puro: il metodo da invocare può essere determinato solo in fase di esecuzione Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 33 PolymorphismDemo // Esempio di polimorfismo puro public class PolymorphismDemo { public static void main(String[] args) { Point[] p = new Point[4]; p[0] p[1] p[2] p[3] = = = = new new new new Colored3DPoint(4, 4, 4, Color.BLACK); ThreeDimensionalPoint(2, 2, 2); ColoredPoint(3, 3, Color.RED); Point(4, 4); for (int i = 0; i < p.length; ++i) { String s = p[i].toString(); System.out.println("p[" + i + "]: " + s); } return; } } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Polimorfismo 34 Esempio 1. Persona r; 2. 3. r = new Studente("Lino", "Torvaldi", 987654); 4. System.out.println(r.toString()); 6. // Lino Torvaldi, matr. 987654. 7. // E NON Lino Torvaldi. 5. System.out.println(r.getMatricola()); 10. // NO, ERRORE (IN COMPILAZIONE)! 9. Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Late Binding public class L { // L(): costruttore predefinito public L() { } // f(): facilitatore public void f() { System.out.println("Uso f() di g(); } // g(): facilitatore public void g() { System.out.println("Uso g() di } } L"); L"); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 35 Late Binding 36 public class M extends L { // M(): costruttore predefinito public M() { // nessun corpo necessario } // g(): facilitatore public void g() { System.out.println("Uso g() di M"); } public static void main(String[] args) { L l = new L(); M m = new M(); l.f(); m.f(); return; } } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Output Uso f() Uso g() Uso f() Uso g() di di di di L L L M Cast 1. 2. Persona p; Studente s; 3. 4. p = new Studente("Letizia", "Arnaboldi", 000000); 5. 6. 7. 8. s = (Studente)p; System.out.println("matr." + s.getMatricola()); // matr. 000000 Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 37 Classe Object 38 Ogni classe implicitamente o esplicitamente estende la classe più generica Object, definita nel package java.lang Metodi toString() equals() clone() getClass() finalize() hashCode() wait(), wait(long), wait(long,int) come si vedrà, i metodi possono essere ridefiniti nelle classi derivate Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Metodo equals 39 Esempio 1. int x,y; // coordinate 2. 3. 4. 5. 6. public boolean equals(Punto p) { // pre: p!=null return (this.x == p.x) && (this.y == p.y); } 7. public boolean equals(Object p) { 9. // pre: p!=null 10. boolean uguali; 11. if (p instanceof Punto) 12. uguali = this.equals((Punto) p); 13. else 14. uguali = false; 15. return uguali; 16. } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 8. Classi: 40 Ereditarietà e Progettazione L’ereditarietà (in generale) è una tecnica che va tenuta in considerazione nella progettazione delle classi prima si progetta la gerarchia delle classi criteri per decidere se una classe può essere definita come estensione di una classe poi vengono implementate le classi Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classi Astratte Una classe astratta è una classe implementata in modo parziale 41 metodi astratti: viene specificata la loro intestazione ma non il loro corpo una classe astratta non può essere istanziata Utilità delle classi astratte definire un comportamento comune le classi derivate dichiarare le funzionalità che devono essere implementate da tutte le classi che la estendono una classe senza metodi astratti è detta concreta Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classi Astratte 42 Esempio Si supponga di voler creare una classe GeometricObject Metodi concreti ragionevoli comprendono getPosition() setPosition() getColor() setColor() paint() Per tutti tranne paint(), è possibile creare implementazioni. Per paint(), occorre conoscere il tipo di oggetto da disegnare: è un quadrato, un triangolo ecc. Il metodo paint() dovrebbe essere un metodo astratto Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classi Astratte 43 Esempio import java.awt.*; abstract public class GeometricObject { Point position; Color color; public Point getPosition() { return position; } public void setPosition(Point p) { position = p; } public Color getColor() { return color; } public void setColor(Color c) { color = c; } } abstract public void paint(Graphics g); Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classe Astratta Forma 1. 2. 44 abstract class Forma { protected String colore; 3. public Forma(String colore) { this.colore = colore; } 4. 5. 6. 7. public String colore() { return colore; } 8. 9. 10. 11. 12. 13. // Ogni forma deve saper calcolare la sua area public abstract double area(); 14. 15. } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classe Concreta Quadrato 1. 2. 45 class Quadrato extends Forma { protected double lato; 3. 4. 5. 6. 7. public Quadrato(double lato, String colore) { super(colore); this.lato = lato; } 8. 9. 10. 11. public double lato() { return lato; } 12. 13. 14. 15. 16. 17. } // Restituisce l'area di questo Quadrato public double area() { return lato*lato; } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Classe Concreta Cerchio 1. 2. 46 class Cerchio extends Forma { protected double raggio; 3. 4. 5. 6. 7. public Cerchio(double raggio, String colore) { super(colore); this.raggio = raggio; } 8. 9. 10. 11. public double raggio() { return raggio; } 12. 13. 14. 15. 16. 17. } // Restituisce l'area di questo Cerchio public double area() { return raggio*raggio*Math.PI; } Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Esempio 47 Uso delle Classi Astratte/Concrete 1. 2. 4. 5. Quadrato q; Forma fq; // un quadrato // un altro quadrato q = new Quadrato(5, "bianco"); fq = new Quadrato(10, "rosso"); 6. 7. 8. 9. System.out.println(q.area()); System.out.println(q.colore()); System.out.println(q.lato()); // 25.0 // bianco // 5.0 10. 11. System.out.println(fq.area()); 12. System.out.println(fq.colore()); // 100.0 // rosso 13. 14. System.out.println(fq.lato()); 15. // NO, errore di compilazione! Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 48 Una interfaccia (interface) descrive un insieme di comportamenti consiste nella dichiarazione di un certo numero di metodi d’istanza e pubblici i metodi sono considerati implicitamente astratti le variabili sono considerate public, final e static una classe implementa (implements) una interfaccia se implementa tutti i metodi d’istanza dichiarati dall’interfaccia Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 49 Un'interfaccia è un modello che specifica che cosa deve essere presente in una classe che implementa l'interfaccia Un'interfaccia non può specificare nessuna implementazione dei metodi Tutti i metodi di un'interfaccia sono pubblici Tutte le variabili definite in un'interfaccia sono public, final e static Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 50 Un'interfaccia per un oggetto colorabile public interface Colorable { public Color getColor(); public void setColor(Color c); } Ora l'interfaccia può essere utilizzata per creare classi che implementano l'interfaccia Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce import java.awt.*; public class ColorablePoint extends Point implements Colorable { Color color; public ColorablePoint() { super(); setColor(Color.blue); } . . . Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA 51 Esempio 52 Interfaccia Comparable 1. 2. 3. 4. 5. 6. 7. 8. 9. public interface Comparable { /* Confronta questo oggetto con o per determinare * in che relazione d'ordine sono. * Restituisce: * - zero, se sono uguali * - un valore negativo, * se questo oggetto è minore di o * - un valore positivo, * se questo oggetto è maggiore di o. */ 10. public int compareTo(Object o); 11. 12. } le classi String e Integer implementano questa interfaccia Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 53 Implementazione // Un oggetto Numero rappresenta un numero intero, // con un valore che può essere letto e modificato. class Numero implements Comparable { private int valore; public Numero(int v) { this.valore = v; } public int getValore() { return this.valore; } public void setValore(int v) { this.valore = v; } ... segue ... Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 54 Implementazione 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. // Verifica la relazione tra numeri. public int compareTo(Numero o) { // pre: o!=null int confronto; if (this.valore==o.valore) confronto = 0; else if (this.valore<o.valore) confronto = -1; else // this.valore>o.valore confronto = 1; return confronto; } 13. 14. 15. 16. 17. 18. 19. // Verifica la rel. tra questo numero e l’oggetto o public int compareTo(Object o) { // pre: o!=null && o instanceof Numero return compareTo((Numero) o); } } // classe Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce e Polimorfismo 55 Una interfaccia definisce un tipo (parziale) che può essere implementato polimorficamente da più classi: il metodo void sort(Object[] a) di Arrays ipotizza che gli elementi di a siano tutti di uno stesso tipo che questo tipo implementi l’interfaccia Comparable si può usare per ordinare un array di oggetti di tipo Numero Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA Interfacce 56 Rappresentazione «interfaccia» Comparable int compareTo(Object o) implementa Numero valore : int «costruttore» Numero(int v) «operazioni» int getValore() void setValore(int v) int compareTo(Numero o) int compareTo(Object o) Corso di Programmazione (IPSW) © 2004 S.Ferilli & N.Fanizzi - dib - UniBA