Polimorfismo Significato Significato Varie famiglie Varie famiglie Polimorfismo in java Polimorfismo in java Polimorfismo di Sottotipo: Apparato in Java Polimorfismo di Sottotipo: Apparato in Java Polimorfismi particolari: container Polimorfismi particolari: container
Significato Polimorfismo = avere più aspetti o forme Polimorfismo = avere più aspetti o forme Generalizza struttura: Generalizza struttura: - rispetto tipi coinvolti meccanismo di astrazione meccanismo di astrazione controllo: astrazioni procedurali controllo: astrazioni procedurali dati: tipi astratti dati: tipi astratti polimorfimo: polimorfimo: - controllo: procedure polimorfe - controllo: procedure polimorfe - dati: tipi polimorfi - dati: tipi polimorfi
Varie Famiglie parametrico: parametrico: - tipi generici (introducono relazioni generiche tra tipi) - esempio: List(T) = null + T x List(T) - public class List {…}; sottotipi sottotipi - gerarchia di tipi (una solo relazione su tutti i tipi) - esempio: classe ObjectList ad hoc ad hoc - strutture con piu significati - esempio: (nomi di) operatori overloaded
Polimorfismo in Java sottotipi: sottotipi: - presente dalla prima definizione di Java - caratteristico degli OOL - discusso sul testo di riferimento parametrico: 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 List{ //O: liste omogenene, non vuote, modificabili di Object,…[x1,..,xn] 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 //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==null) {head=v; return;} if (head.getClass()!=v.getClass()) throw new CCE(“…”); if (head.getClass()!=v.getClass()) throw new CCE(“…”); tail=new List(head,tail); tail=new List(head,tail); head=v;} 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 public class OrderedList{ //O: liste omogenee, non vuote, ordinate, modificabili di Object … private comparable head; private OrderedList up; private OrderedList down; //AF(c)=..//I(c)=.. 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(); if (head==null) {up=new orderedList(); down=new OrderedList(); head=v; return;} head=v; return;} int n=head.compareTo(v); int n=head.compareTo(v); if(n==0 | n>0) up.cons(v); if(n==0 | n>0) up.cons(v); else down.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 Esattamente stesso tipo Un sottotipo di quello di head: head.getClass()).isInstance(v)
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 == null) {head =v; return;} if (head.getClass() != v.getClass()) throw new CCE(“…”); if (head.getClass() != v.getClass()) throw new CCE(“…”); if (occur(v)) throw new DOE(“…”); if (occur(v)) throw new DOE(“…”); tail=new List(head,tail); tail=new List(head,tail); head=v;} 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; if (tail == null) return false; return tail.occurs(v);} 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 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;} 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 == null) {head =v; return;} if (head.getClass() != v.getClass()) throw new CCE(“…”); if (head.getClass() != v.getClass()) throw new CCE(“…”); if (occur(v)) throw new DOE(“…”); if (occur(v)) throw new DOE(“…”); tail=new List(head,tail); tail=new List(head,tail); head=v;} 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; if (tail == null) return false; return tail.occurs(v);} return tail.occurs(v);}…… //O:…. Usiamo containers con cui wrap-unwrap gli objects //O:…. Usiamo containers con cui wrap-unwrap gli objects 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 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 => 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);} return (el == (Container) v.el);}
Container: una tabellina effectsmodificabiliNon modificabiliContainer (con solo modificabili) = puntatoriOKNo equalsStato (rep)NoOK public class FunContainers extends Containers{ //O: FunContainer sono Containers. Due FunContainers sono // equals se e solo se contengono lo stesso Fun private Fun el; //AF(c)=AF(c.el)//I(c)=el≠null; public container(Object v) throws CCE, NPE //E: crea container per v {el=(Fun)v;} public Object get() //E: unwrapping {return el;} public boolean equals(Object v) {Class T= Class.forName(“FunContainers”); if(!(T.isInstance(v)) return false; if(!(T.isInstance(v)) return false; return (el == (Fun) v.el.get());} return (el == (Fun) v.el.get());} public class SetContainers extends Containers{ //O: SetContainer sono Containers. Due SetContainers sono // equals se e solo se i Set contenuti sono strutturalmente identici private Set el; //AF(c)=AF(c.el)//I(c)=el≠null; public container(Object v) throws CCE, NPE //E: crea container per v {el=(Set)v;} public Object get() //E: unwrapping {return el;} public boolean equals(Object v) {Class T= Class.forName(“SetContainers”); if(!(T.isInstance(v)) return false; if(!(T.isInstance(v)) return false; return (el.equals((Set) v.el.get()));} 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{ //O: mutable set di oggetti con operazione sum degli oggetti dello // insieme. Tali oggetti sono related subtype di un interfaccia adder private Adder a; // oggetto del related subtype private Vector els; // per gli elementi Private Object s; // somma degli elementi //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() && (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)) && s= 0≤i<c.els.size() c.a.sum(c.a,c.els.get(i)) public SumSet(Adder p)throws NPE //E: crea insieme vuoto {els=new Vector(); a=p; s=a.zero(); } public void insert(Object x) throws CCE, NPE //M: this // E: aggiunge v e modifica la somma {if (!isIn(x)) {s=a.add(s,x); els.add(x);} } 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(“…”); if (a.getClass()!=x.getClass()) throw new CCE(“…”); int i; for(i=0; i<els.size() && !x.equals(els.get(i)); i++); int i; for(i=0; i<els.size() && !x.equals(els.get(i)); i++); return (i!=els.size()); return (i!=els.size()); }…; } public class IntAdder implements Adder{ //O: una related subtype per Integer con operazioni add,sub, zero private Integer a; public IntAdder() //E: sceglie 0 per a {a = new Integer(0);} public Object add(Object x, Object y) throws CCE, NPE //E: calcola oggetto somma se esiste {if (x==null || y==null) throw new NPE(“…”); if (!isInteger(x) || !isInteger(y) throw new CCE(“…”); if (!isInteger(x) || !isInteger(y) throw new CCE(“…”); return new Integer((Integer)x.intValue()+ ((Integer)y.intValue())} return new Integer((Integer)x.intValue()+ ((Integer)y.intValue())} public Object sub(Object x, Object y) throws CCE, NPE //E: calcola oggetto sottrazione se esiste {if (x==null || y==null) throw new NPE(“…”); if (!isInteger(x) || !isInteger(y) throw new CCE(“…”); if (!isInteger(x) || !isInteger(y) throw new CCE(“…”); return new Integer((Integer)x.intValue()-((Integer)y.intValue())} return new Integer((Integer)x.intValue()-((Integer)y.intValue())} public Object zero() //E: calcola oggetto sottrazione se esiste {return a;} private boolean isInteger(Object x){ return( x.getClass()==a.getClass()} return( x.getClass()==a.getClass()}} public class VectAdder extends Adder{ //O: una related subtype per Vectors con operazioni add,sub, zero private Vector a; public Object VectAdder() …