Polimorfismo
•
Significato
• Varie famiglie
• Polimorfismo in java
• Polimorfismo di Sottotipo: Apparato in Java
• Polimorfismi particolari: container
Significato
• Polimorfismo = avere più aspetti o forme
• Generalizza struttura:
- rispetto tipi coinvolti
• meccanismo di astrazione
• controllo: astrazioni procedurali
• dati: tipi astratti
• polimorfimo:
- controllo: procedure polimorfe
- dati: tipi polimorfi
Varie Famiglie
• parametrico:
- tipi generici (introducono relazioni generiche tra tipi)
- esempio: List(T) = null + T x List(T)
public class List<T>{…};
• sottotipi
- gerarchia di tipi (una solo relazione su tutti i tipi)
- esempio: classe ObjectList
• ad hoc
- strutture con piu significati
- esempio: (nomi di) operatori overloaded
Polimorfismo in Java
• sottotipi:
- presente dalla prima definizione di Java
- caratteristico degli OOL
- discusso sul testo di riferimento
• parametrico:
- presente nell’ultima estensione (java 1.5)
- caratteristico dei funzionali
- non lo consideriamo (per ora)
Polimorfismo di Sottotipo:
Apparato in Java
public class P_morphic{
//O: una P_morphic classe che astrae sul super_tipo A
-- rep contiene riferimenti ad A
public P_morphic(par)
//E: inizializzazione di rep può richiedere A nei parametri
public T1 m1(par1)
//può coinvolgere metodi di A
….
public Tk mk(park)
//può coinvolgere metodi di A
Liste omogenee e Liste ordinate
public class OrderedList{
public class List{
//O: liste omogenene, non vuote, modificabili di Object,…[x1,..,xn]
private Object head;
private List tail;
//AF(c)=..
//I(c)=..
//O: liste omogenee, non vuote, ordinate, modificabili di Object …
private comparable head;
private OrderedList up;
private OrderedList down;
//AF(c)=..
//I(c)=..
private List(Object v, List L)
//E: crea lista interna [v,x1,…,xn] con AF(L)= [x1,…,xn]
{head=v; tail=L;}
public void cons(Object v) throws CCE, NPE
//E: se v è null solleva eccezioneNPE, se tail è non null e ha tipo diverso da
// quello di v allora solleva eccezione CCE, altrimenti aggiungi come primo
// elemento
{if (v==null) throw new NPP(“…”);
if (head==null) {head=v; return;}
if (head.getClass()!=v.getClass()) throw new CCE(“…”);
tail=new List(head,tail);
head=v;}
public void drop()
//E: rimuove il primo elemento se presente altrimenti nulla
public Object head() throws ELE
//E: restituisce il primo elemento se presente, altrimenti EmpListExc
Esattamente stesso tipo
Un sottotipo di quello di head:
head.getClass()).isInstance(v)
private OrderedList()
//E: crea lista indefinita -- non accessibile
{}
public void cons(comparable v) throws CCE, NPE
//E: se v è null solleva eccezioneNPE, se tail è non null e non è confrontabile con
// v allora solleva eccezione CCE, altrimenti aggiungi ordinatamente
{if (v==null) throw new NPP(“…”);
if (head==null) {up=new orderedList(); down=new OrderedList();
head=v; return;}
int n=head.compareTo(v);
if(n==0 | n>0) up.cons(v);
else down.cons(v);}
public void drop()
//E: rimuove il primo elemento se presente altrimenti nulla
public Object head() throws ELE
//E: restituisce il primo elemento se presente, altrimenti EmpListExc
Situazioni particolari: Container
public class SList{
//O: liste omogenene, modificabili di Object occorrenti una sola
volta
private Object head;
private List tail;
//AF(c)=..
//I(c)=..
private List(Object v, List L)
//E: crea lista interna [v,x1,…,xn] con AF(L)= [x1,…,xn]
{head=v; tail=L;}
public void cons(Object v) throws CCE, NPE, DOE
//E: se v è null solleva eccezioneNPE, se tail è non null e ha tipo diverso da
// quello di v allora solleva eccezione CCE, se ha valore uguale a quello di v
// allora solleva eccezione DOE, altrimenti aggiungilo come primo elemento.
{if (v==null) throw new NPP(“…”);
if (head == null) {head =v; return;}
if (head.getClass() != v.getClass()) throw new CCE(“…”);
if (occur(v)) throw new DOE(“…”);
tail=new List(head,tail);
head=v;}
public void drop()
//E: rimuove il primo elemento se presente altrimenti nulla
public Object head() throws ELE
//E: restituisce il primo elemento se presente, altrimenti EmpListExc
private boolean occurs(Object v)
//R: v!=null & head!=null => tail.getClass() == v.getClass()
//E: calcola true se v occorre in this, false altrimenti.
{if (v.equals(head)) return true;
if (tail == null) return false;
return tail.occurs(v);}
Applichiamola: Valutiamo le sequenze
Integer n1 = new Integer(3);
Integer n2 = new Integer(3);
Integer n3 = new Integer(3);
cons(n1,cons(n2,cons(3, empty()))))
==================================
Vector v1 = new Vector();
Vector v2 = newVector();
Vector v3 = new Vector();
cons(n1,cons(n2,cons(3, empty())))
========================================
Set i1 = new Set();
Set i2 = new Set();
cons(i1,cons(i2,empty()))
========================================
Fun f1 = new Fun();
Fun f2 = new Fun();
cons(f1,cons(f2,empty()));
Situazioni particolari: Container
public class SList{
……
//O: liste omogenene, modificabili di Object occorrenti una sola
volta
//O:…. Usiamo containers con cui wrap-unwrap gli objects
private Object head;
private List tail;
//AF(c)=..
//I(c)=..
private List(Object v, List L)
//E: crea lista intermedia [v,,x1,…,xn] con AF(L)= [x1,…,xn]
{head=v; tail=L;}
private Container head;
private List tail; …
…
public void cons(Container v) throws CCE, NPE, DOE
//E: se v è null solleva eccezioneNPE, se tail è non null e ha tipo diverso da
//quello di v allora solleva eccezione CCE, se ha valore uguale a quello di v
// allora solleva eccezione DOE, altrimenti aggiungilo come primo elemento.
{…}
public void cons(Object v) throws CCE, NPE, DOE
public void drop()
//E: se v è null solleva eccezioneNPE, se tail è non null e ha tipo diverso da
// quello di v allora solleva eccezione CCE, se ha valore uguale a quello di v
// allora solleva eccezione DOE, altrimenti aggiungilo come primo elemento.
//E: rimuove il primo elemento se presente altrimenti nulla
public Object head() throws ELE
{if (v==null) throw new NPP(“…”);
if (head == null) {head =v; return;}
if (head.getClass() != v.getClass()) throw new CCE(“…”);
if (occur(v)) throw new DOE(“…”);
tail=new List(head,tail);
head=v;}
private boolean occurs(Object v)
public void drop()
//E: rimuove il primo elemento se presente altrimenti nulla
public Object head() throws ELE
//E: restituisce il primo elemento se presente, altrimenti EmpListExc
private boolean occurs(Object v)
//R: v!=null & head!=null => tail.getClass() == v.getClass()
//E: calcola true se v occorre in this, false altrimenti.
{if (v.equals(head)) return true;
if (tail == null) return false;
return tail.occurs(v);}
//E: restituisce il primo elemento se presente, altrimenti EmpListExc
//R: v!=null & head!=null => head.getClass() == v.getClass()
//E: calcola true se v occorre in this, false altrimenti.{…}
public class container{
//O: Container sono immutable, contengono un singolo oggetto. Due
// container sono equals se e solo se contengono lo stesso oggetto
private Container el;
//AF(c)=AF(c.el)
//I(c)=el≠null;
public container(Object v)
//E: crea container per v {el=(Fun)v;}
public Object get()
//E: unwrapping
{return el;}
public boolean equals(Object v)
{if(!( Class.forName(“Container”)).isInstance(v)) return false;
return (el == (Container) v.el);}
Container: una tabellina
effects
==
equals
modificabili
Non modificabili
Container (con solo
modificabili)
puntatori
OK
No
No
Stato (rep)
No
OK
OK
public class FunContainers extends Containers{
public class SetContainers extends Containers{
//O: FunContainer sono Containers. Due FunContainers sono
// equals se e solo se contengono lo stesso Fun
//O: SetContainer sono Containers. Due SetContainers sono
// equals se e solo se i Set contenuti sono strutturalmente identici
private Fun el;
private Set el;
//AF(c)=AF(c.el)
//I(c)=el≠null;
//AF(c)=AF(c.el)
//I(c)=el≠null;
public container(Object v) throws CCE, NPE
public container(Object v) throws CCE, NPE
//E: crea container per v {el=(Fun)v;}
//E: crea container per v {el=(Set)v;}
public Object get()
public Object get()
//E: unwrapping
{return el;}
//E: unwrapping
{return el;}
public boolean equals(Object v)
public boolean equals(Object v)
{Class T= Class.forName(“FunContainers”);
if(!(T.isInstance(v)) return false;
return (el == (Fun) v.el.get());}
{Class T= Class.forName(“SetContainers”);
if(!(T.isInstance(v)) return false;
return (el.equals((Set) v.el.get()));}
Fun sono modificabili
Set sono nonModificabili
Situazioni particolari:
Related Subtype
public class P_morphic{
//O: una P_morphic classe che astrae sul super_tipo A
-- rep contiene riferimenti ad A
public P_morphic(par)
// inizializzazione di rep può richiedere A nei parametri
public T1 m1(par1)
//può coinvolgere metodi di A
….
public Tk mk(park)
//può coinvolgere metodi di A
Quando un supertipo A non c’è?
- Creiamo una gerarchia di tipi correlati
- Definiamo P_morphic su tale gerarchia
Situazioni particolari: Adder
public class SumSet{
public class IntAdder implements Adder{
//O: mutable set di oggetti con operazione sum degli oggetti dello
// insieme. Tali oggetti sono related subtype di un interfaccia adder
//O: una related subtype per Integer con operazioni add,sub, zero
private Integer a;
public IntAdder()
private Adder a; // oggetto del related subtype
private Vector els; // per gli elementi
Private Object s; // somma degli elementi
//E: sceglie 0 per a
{a = new Integer(0);}
//AF(c)={c.els.get(i)|0≤i<c.els.size()}
//I(c)= c.els!=null && c.a.equals(c.a.sum(c.a,c.a))
&& (0≤i<c.els.size()) c.a.getClass()==c.els.get(i).getClass()
&& s=0≤i<c.els.size()c.a.sum(c.a,c.els.get(i))
public Object add(Object x, Object y) throws CCE, NPE
//E: calcola oggetto somma se esiste
//E: crea insieme vuoto
{if (x==null || y==null) throw new NPE(“…”);
if (!isInteger(x) || !isInteger(y) throw new CCE(“…”);
return new Integer((Integer)x.intValue()+ ((Integer)y.intValue())}
{els=new Vector(); a=p; s=a.zero();
}
//E: calcola oggetto sottrazione se esiste
public SumSet(Adder p)throws NPE
public Object sub(Object x, Object y) throws CCE, NPE
{if (x==null || y==null) throw new NPE(“…”);
if (!isInteger(x) || !isInteger(y) throw new CCE(“…”);
return new Integer((Integer)x.intValue()-((Integer)y.intValue())}
public void insert(Object x) throws CCE, NPE
//M: this
// E: aggiunge v e modifica la somma
public Object zero()
{if (!isIn(x)) {s=a.add(s,x); els.add(x);}
}
//E: calcola oggetto sottrazione se esiste
{return a;}
private boolean isInteger(Object x){
return( x.getClass()==a.getClass()}
public Object sum()
//E: somma degli elementi
{return s;
}
}
public boolean isIn(x) throws CCE,NPE
//E: true see x appartiene all’insieme
//E: calcola true se v occorre in this, false altrimenti.
{if (v==null) throw NPE(“…”);
if (a.getClass()!=x.getClass()) throw new CCE(“…”);
int i; for(i=0; i<els.size() && !x.equals(els.get(i)); i++);
return (i!=els.size());
}…;
}
public class VectAdder extends Adder{
//O: una related subtype per Vectors con operazioni add,sub, zero
private Vector a;
public Object VectAdder()
…
Scarica

copia dei lucidi