Scaricare il libro Eloge de la fuite

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
}