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() …