Polimorfismo - Genericità Vitaliano Milanese Dipartimento di Matematica e Informatica Università di Udine Programmazione Object Oriented :: Lezione 7 2 POLIMORFISMO In generale si indica con il termine • polimorfismo la proprietà di una funzione di assumere comportamenti differenziati Ciò si concretizza nella proprietà di ottenere comportamenti diversificati da parte degli oggetti in risposta ad uno stesso messaggio 3 POLIMORFISMO Messaggio polimorfo (interpretazione forte) Messaggio elaborabile da classi diverse strutturate gerarchicamente mediante metodi aventi la stessa intestazione • Tipico nel caso di ereditarietà singola • Causato dall’ esistenza di più metodi con eguale segnatura contestualmente noti nell’ ambiente di supporto al programma in esecuzione Messaggio polimorfo (interpretazione debole) Messaggio elaborabile da un metodo selezionato in una famiglia di metodi parametrici affini sulla base dei tipi specificati per i propri parametri • Tipico dei linguaggi con ereditarietà multipla e dotati di classi parametriche • Può essere realizzato (parzialmente) anche in ereditarietà singola 4 POLIMORFISMO Al polimorfismo (interpretazione forte) sono legati due aspetti realizzativi: • primo aspetto meccanismo mediante il quale un singolo metodo può essere definito in più classi con implementazioni differenziate • secondo aspetto meccanismo per mezzo del quale una variabile (attributo) può puntare oggetti diversi in tempi diversi 5 POLIMORFISMO Primo aspetto Esempio Poligono / area : Misura2D calcolaArea (out area : Misura2D) Triangolo calcolaArea (out area : Misura2D) Rettangolo Esagono calcolaArea (out area : Misura2D) • calcolaArea() di Poligono metodo generico di determinazione d’area usato da oggetti Poligono e Esagono (ereditato) • calcolaArea() di Triangolo metodo specifico per triangoli usato da oggetti Triangolo (sovrascritto) • calcolaArea() di Rettangolo metodo specifico per rettangoli usato da oggetti Rettangolo (sovrascritto) 6 POLIMORFISMO Poligono geometria; Triangolo t = new Triangolo (...); Rettangolo r = new Rettangolo (...); Esagono e = new Esagono (...); Esempio Secondo aspetto geometria = e; if ( certaCondizione ) geometria = t; else if ( altraCondizione ) geometria = r; La variabile geometria può puntare a oggetti di tipo diverso • poichè e (Esagono), t (Triangolo), r (Rettangolo) sono anche di tipo Poligono • è utilizzato il late binding il legame tra gli identificatori e gli oggetti da essi puntati avviene a tempo di esecuzione e non di compilazione 7 POLIMORFISMO L’utilizzo di sovraclassi da cui far ereditare metodi comuni da specializzare nelle classi derivate e la possibilità di far puntare ad uno stesso identificatore sia oggetti della classe che delle sue sottoclassi permette di estendere l’insieme delle classi disponibili (Triangolo, Rettangolo, Esagono) con ulteriori classi (Pentagono, Dodecagono, ... ) dotate degli stessi metodi polimorfici senza aggravi alla progettazione d’insieme delle applicazioni TUTTAVIA Ciò non forza le nuove classi ad implementare i metodi richiesti e ad esse necessari 8 POLIMORFISMO Generare forme geometriche di tipologia differenziata da sottoporre a operazioni di traslazione PROBLEMA TIPICO 9 METODI e CLASSI ASTRATTE Un modo per forzare l’ implementazione di un metodo in una o più classi è di ricorrere a (sovra)classi astratte • Un metodo astratto non possiede alcuna implementazione La procedura modellata ha una propria segnatura e una funzionalità definita ma nessun codice di implementazione effettivo • Una classe astratta (tipicamente) contiene almeno un metodo astratto Non può essere istanziata I metodi devono essere implementati nelle sottoclassi 10 METODI e CLASSI ASTRATTE SINTASSI Una classe astratta va dichiarata abstract I metodi astratti di una classe astratta: • vanno dichiarati abstract • sono privi di corpo abstract class <iden> { abstract <idenMetodo> ( <parametri> ); …… abstract <idenMetodo> ( <parametri> ); // Eventuali dichiarazioni di attributi della classe // Eventuali altri metodi concreti della classe } 11 METODI e CLASSI ASTRATTE UTILITA` • Sono impiegabili quali radici di gerarchie di classi con specifiche comuni • Permettono di raggruppare oggetti altrimenti afferibili a classi diverse • Sfruttano il polimorfismo e il late-binding in modo flessibile dal momento che è possibile dichiarare oggetti afferenti a classi astratte 12 BINDING In presenza di catene di classi legate per ereditarietà con overriding di metodi va considerato il binding tra le variabili contenenti le istanze delle classi e i metodi chiamati public class ClsA { protected void m() { System.out.println ( "Classe ClsA" ); } } public class ClsB extends ClsA { protected void m() { System.out.println ( "Classe ClsB" ); } } 13 BINDING public class ProvaBinding { public static void main (String[] args) { ClsA a = new ClsA (); ClsB b = new ClsB (); a.m (); b.m (); a = b; a.m (); } } Uscita prodotta: Classe ClsA Classe ClsB Classe ClsB // a.m (); // b.m (); // a.m (); 14 BINDING Late binding L’ associazione tra il nome del metodo e il metodo invocato è stabilita a tempo di esecuzione sulla base dell’ oggetto sostenuto dalla variabile a cui il messaggio è inoltrato Early binding L’ associazione tra il nome del metodo e il metodo invocato è stabilita a tempo di compilazione in base alla classe dichiarata per la variabile a cui il messaggio è inoltrato 15 LATE BINDING ClsA heap m() objA a m() ClsB m() objB m() b ClsA a = new ClsA(); ClsB b = new ClsB(); a.m(); b.m(); 16 LATE BINDING ClsA heap a = b; a.m(); m() objA a m() ClsB m() objB m() b 17 CASTING E` possibile assegnare a variabili di una classe oggetti di una (sotto)classe Non è possibile assegnare direttamente a variabili di una (sotto)classe oggetti della (sovra)classe: • è necessario un cast esplicito: in generale la (sotto)classe contiene un maggior numero di attributi e metodi • in esecuzione il metodo può fallire public class ProvaBinding { public static void main (String[] args) { ClsA a = new ClsA (); ClsB b = new ClsB (); a.m (); b.m (); } } b = (ClsB) a; // Richiesto cast esplicito in compilazione b.m (); // Sollevata ClassCastException in esecuzione 18 POLIMORFISMO (PROBLEMA) Classe Base • IdenClasse astratta: corsivo maiuscolo + specifica { abstract } • IdenMetodo astratto: corsivo minuscolo + specifica { abstract } Figura { abstract } trasla (in dx, dy : Intero) { abstract } contains (in p : Point2D; out __ : Boolean) { abstract } draw (in g : Graphics) { abstract } Operazioni imposte da Figura alle sottoclassi: • traslazione di un quadrato / cerchio / ... • verifica di punto interno (ovvero esterno) a un quadrato / cerchio / ... • tracciatura di un quadrato / cerchio / ... 19 POLIMORFISMO (PROBLEMA) 1A Classe Derivata Figura { abstract } trasla (in dx, dy : Intero) { abstract } contains (in p : Point2D; out __ : Boolean) { abstract } draw (in g : Graphics) { abstract } Quadrato Quadrato (in vertSupSx : Point2D; in lato : Intero) trasla (in dx, dy : Intero) contains (in p : Point2D; out __ : Boolean) draw (in g : Graphics) Operazioni disponibili: • • • • istanzazione di oggetti di tipo Quadrato traslazione di un quadrato verifica di punto interno (ovvero esterno) ad un quadrato tracciatura di un quadrato 20 POLIMORFISMO (PROBLEMA) 2A Classe Derivata Figura { abstract } trasla (in dx, dy : Intero) { abstract } contains (in p : Point2D; out __ : Boolean) { abstract } draw (in g : Graphics) { abstract } Cerchio Cerchio (in centro : Point2D; in raggio : Intero) trasla (in dx, dy : Intero) contains (in p : Point2D; out __ : Boolean) draw (in g : Graphics) Operazioni disponibili: • • • • istanzazione di oggetti di tipo Cerchio traslazione di un cerchio verifica di punto interno (ovvero esterno) ad un cerchio tracciatura di un cerchio 21 POLIMORFISMO CLASSE Figura Codifica Java CLASSE BASE ASTRATTA public abstract class Figura { public abstract void draw (Graphics g); public abstract void trasla (int dx, int dy); public abstract boolean contains (Point2D p); } 22 POLIMORFISMO CLASSE Quadrato 1^ CLASSE DERIVATA public class Quadrato extends Figura { private Point2D vertSupSx; private int lato; public Quadrato (Point2D vertSupSx, int lato) { this.vertSupSx = vertSupSx; this.lato = lato; } public void draw (Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.fill (new Rectangle2D.Double (vertSupSx.getX(), vertSupSx.getY(), lato, lato)); } Continua ... 23 POLIMORFISMO CLASSE Quadrato 1^ CLASSE DERIVATA public void trasla (int dx, int dy) { vertSupSx = new Point2D.Double (vertSupSx.getX() + dx, vertSupSx.getY() + dy); } public boolean contains (Point2D p) { Rectangle2D r = new Rectangle2D.Double (vertSupSx.getX(), vertSupSx.getY(), lato, lato); return r.contains (p); } } 24 POLIMORFISMO CLASSE Cerchio 2^ CLASSE DERIVATA public class Cerchio extends Figura { private Point2D centro; private int raggio; public Cerchio (Point2D centro, int raggio) { this.centro = centro; this.raggio = raggio; } public void draw (Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.fill (new Ellipse2D.Double (centro.getX() - raggio, centro.getY() - raggio, 2*raggio, 2*raggio)); } Continua ... 25 POLIMORFISMO CLASSE Cerchio 2^ CLASSE DERIVATA public void trasla (int dx, int dy) { centro = new Point2D.Double (centro.getX() + dx, centro.getY() + dy); } public boolean contains (Point2D p) { Ellipse2D e = new Ellipse2D.Double (centro.getX() - raggio, centro.getY() - raggio, 2*raggio, 2*raggio); return e.contains (p); } } 26 POLIMORFISMO Utilizzo L’utilizzo del polimorfismo è legato principalmente alla proprietà • upcasting possibilità di assegnare a tempo di esecuzione ad un identificatore di oggetti di una certa classe anche oggetti istanziati da sottoclassi da essa derivate L’ upcasting permette di utilizzare una variabile generica (della sovraclasse) • per puntare oggetti istanziati da sottoclassi • inoltrare ad essa messaggi comuni da risolvere con metodi specifici alle sottoclassi 27 POLIMORFISMO Utilizzo public class GeometrieApplet ...... { private Figura[] geometrie = new Figura[2]; public void init() { geometrie[0] = new Cerchio (new Point2D.Double (50, 50), 20); geometrie[1] = new Quadrato (new Point2D.Double (30, 90), 40); } public void paint (Graphics g) { for (int k = 0; k < geometrie.length; k++) geometrie[k].draw (g); } Continua ... 28 POLIMORFISMO Segue public void mousePressed (MouseEvent ev) { p1 = ...... } public void mouseReleased (MouseEvent ev) { p2 = ...... ; dx = p2.getX() - p1.getX(); dy = p2.getY() - p1.getY(); for (int k = 0; k < geometrie.length; k++) if (geometrie[k].contains (p1)) geometrie[k].trasla (dx,dy); ...... } } Utilizzo 29 POLIMORFISMO Upcasting in sintesi ClsA idenObj ClsB objB Gestione handle ClsA idenObj; ClsB objB = new ClsB (); idenObj = objB; 30 POLIMORFISMO idenObj . m() Upcasting in sintesi ClsA idenObj ClsB objB Gestione messaggi Gestione metodi messaggio ricevuto da idenObj che riferisce objB Quindi m() deve esistere in ClsB: - definito nella classe - ereditato da sovraclasse ricevuto da objB polimorfismo - riscritto da sovraclasse - riscritto da sovraclasse astratta 31 GENERICITA’ Si indica con il termine • genericità il meccanismo con cui una classe può essere completata a tempo di esecuzione in relazione alle classi interne da essa utilizzate Tipicamente la genericità è utilizzare per costruire classi contenitore: • i cui elementi informativi possono variare con l’applicazione • la struttura organizzativa delle informazioni e i metodi da applicare alla struttura sono indipendenti dalla tipologia delle informazioni contenute 32 GENERICITA’ PROBLEMA Progettare un albero binario ordinato e bilanciato da utilizzare per registrare entità che siano riferibili a domini ordinati generici 72 44 12 m4 84 52 Informazioni nodi numeriche cc 91 t3 cg zz Informazioni nodi stringhe 33 CLASSI PARAMETRICHE e CLASSI LEGATE Classi contenitore possono essere costruite ricorrendo alle classi parametriche Definiscono modelli organizzativi per oggetti similari nelle funzionalità ma dotati di componenti afferenti a domini diversi • Una classe parametrica è una classe dipendente da uno o più parametri formali Parte degli attributi e/o dei metodi della classe sono definiti in funzione dei parametri formali della classe • Una classe parametrica dà luogo ad una classe legata quando i parametri formali sono sostituiti da classi effettive 34 UML Classi Parametriche e Classi Legate P1, … ,Pn IdenClasseParametrica sezione attributi Classe parametrica P1, … , Pn parametri formali sezione metodi IdenClasseParametrica <C1, … ,Cn> sezione attributi sezione metodi Classe legata C1, … Cn parametri attuali (classi) 35 GENERICITA’ (PROBLEMA) Classe Parametrica ClsNodo Albero # radice : ClsNodo Albero() inserisci (in nd : ClsNodo) rimuovi (in nd : ClsNodo) esiste (in nd : ClsNodo; out __ : Boolean) isVuoto (out __ : Boolean) stampa () Vincolo per l’utilizzo della classe: • da essa devono essere derivate classi legate previa sostituzione del parametro formale ClsNodo con classi effettive 36 GENERICITA’ (PROBLEMA) Classi Legate ClsNodo Albero # radice : ClsNodo Albero() inserisci (in nd : ClsNodo) rimuovi (in nd : ClsNodo) esiste (in nd : ClsNodo; out __ : Boolean) isVuoto (out __ : Boolean) stampa () Albero <Intero> Albero <String> sezione attributi sezione attributi sezione metodi sezione metodi 37 GENERICITA’ REALIZZAZIONE Nei linguaggi a classi la genericità è implementabile mediante template oppure classi generiche Template (C++) una specifica di interfacciamento parametrica rispetto ai tipi + un insieme di implementazioni adatte ai diversi possibili tipi concreti Istanzazione di oggetti Da sottoclassi ottenute estendendo il template e specificando i tipi concreti di interesse 38 GENERICITA’ REALIZZAZIONE Classi generiche (Java) Una unica specifica di classe parametrica rispetto ai tipi Istanzazione di oggetti Specificando nell’attivazione del costruttore (new) i tipi concreti di interesse • I parametri formali dei tipi sono usati dal compilatore per verificare la consistenza dei metodi definiti nella classe • Sono sostituiti dai parametri attuali in fase di creazione degli oggetti Effetti collaterali Gli attributi static sono unici nella definizione di classe i.e. per tutti gli oggetti istanziabili indipendentemente dal tipo attuale specificato 39 GENERICITA’ ESEMPIO Visualizzare forme geometriche di tipologia differenziata generate a partire dai loro dati caratteristici e allocate in due sequenze distinte: • la prima riservata ai quadrati • la seconda ai cerchi 40 GENERICITA’ ESEMPIO public class Quadrato { ...... public Quadrato (Point2D vertSupSx, int lato) { ...... } public void draw (Graphics g) { ...... } public void trasla (int dx, int dy) { ...... } public boolean contains (Point2D p) { ...... } } Classi di modellazione delle geometrie public class Cerchio { ...... public Cerchio (Point2D centro, int raggio) { ...... } public void draw (Graphics g) { ...... } public void trasla (int dx, int dy) { ...... } public boolean contains (Point2D p) { ...... } } 41 GENERICITA’ ESEMPIO public class Sequenza<E> { private class Nodo { public E info; public Nodo ptr; Classe generica di modellazione delle sequenze public Nodo (E info, Nodo ptr) { this.info = info; this.ptr = ptr; } } private Nodo pFirst, pLast, pCur; public Sequenza() { pFirst = pLast = pCur = null; } public void addItem (E info) { Nodo nd = new Nodo (info, null); if (pFirst == null) pCur = pFirst = pLast = nd; else { pLast.ptr = nd; pCur = pLast = nd; } } Continua ... 42 GENERICITA’ Segue public boolean isEmpty() { return pFirst == null; } public void setToFirst () { pCur = pFirst; } public E getItem() { return pCur.info; } public boolean existsNext() { return pCur.ptr != null; } public void setToNext() { pCur = pCur.ptr; } } ESEMPIO 43 GENERICITA’ ESEMPIO public class ClsParam extends ...... { private ShapePanel crcPanel, qdrPanel; private DrawPanel drawPanel; public void init() { // Configura l’interfaccia grafica } class ShapePanel extends ...... { ...... public int[][] getData() { ...... } } Modellazione dei pannelli di acquisizione dati Continua ... 44 GENERICITA’ class DrawPanel extends ...... { private Sequenza<Cerchio> seqCrc; private Sequenza<Quadrato> seqQdr; ESEMPIO Modellazione del pannello di visualizzazione public void setCerchio (Sequenza<Cerchio> seqCrc) { this.seqCrc = seqCrc; } public void setQuadrato (Sequenza<Quadrato> seqQdr) { this.seqQdr = seqQdr; } public void paintComponent (Graphics g) { ...... if (seqCrc != null) if (! seqCrc.isEmpty()) { seqCrc.setToFirst(); Cerchio crc = seqCrc.getItem(); crc.draw (g2); while (seqCrc.existsNext()) { seqCrc.setToNext(); crc = seqCrc.getItem(); crc.draw (g2); } } Continua ... 45 GENERICITA’ ESEMPIO Segue if (seqQdr != null) if (! seqQdr.isEmpty()) { seqQdr.setToFirst(); Quadrato qdr = seqQdr.getItem(); qdr.draw (g2); while (seqQdr.existsNext()) { seqQdr.setToNext(); qdr = seqQdr.getItem(); qdr.draw (g2); } } } } // Fine classe interna DrawPanel Continua ... 46 GENERICITA’ ESEMPIO class AscButton implements ...... { private int[][] dataCrc, dataQdr; private Sequenza<Cerchio> seqCrc; private Sequenza<Quadrato> seqQdr; Modellazione del processo di visualizzazione public void actionPerformed (ActionEvent ev) { seqCrc = new Sequenza<Cerchio> (); seqQdr = new Sequenza<Quadrato> (); dataCrc = crcPanel.getData(); for (int k = 0; k < dataCrc.length; k++) { Cerchio crc = new Cerchio (new Point2D.Double (dataCrc[k][0], dataCrc[k][1]), dataCrc[k][2]); seqCrc.addItem (crc); } drawPanel.setCerchio (seqCrc); drawPanel.repaint(); Continua ... 47 GENERICITA’ ESEMPIO Segue dataQdr = qdrPanel.getData(); for (int k = 0; k < dataQdr.length; k++) { Quadrato qdr = new Quadrato (new Point2D.Double (dataQdr[k][0], dataQdr[k][1]), dataQdr[k][2]); seqQdr.addItem (qdr); } drawPanel.setQuadrato (seqQdr); drawPanel.repaint(); } } // Fine classe interna AscButton }
© Copyright 2024 Paperzz