PolyFun
Dare implementazione,funzione di astrazione, invarianti della rappresentazione. Provare che i metodi apply e bind preservano gli invarianti. public class PolyFun { // OVERVIEW: un PolyFun è una funzione // parziale(a dominio finito) da un tipo // qualunque a qualunque altro. E’ // modificabile.Dominio e codominio devono // essere omogenei. // Costruttore public PolyFun (Class dt, Class ct) // EFFECTS: costruisce una nuova PolyFun // avente come dominio dt e come codominio // ct e indefinita per tutti gli argomenti.
// metodi public boolean defined (Object o) // EFFECTS: se this è definita per l'argomento // o ritorna true altrimenti ritorna false. public Object apply (Object o) throws UndefinedException // EFFECTS: se la funzione this è definita per // l'oggetto o restituisce this(o) altrimenti // solleva l'eccezione (unchecked) // UndefinedException.
public void bind (Object d, Object c) throws DuplicateException, ClassCastException, NullPointerException { //MODIFIES:this // EFFECTS: modifica this in modo che la //funzione sia definita anche // per d e applicata a d restituisce c. // Se this è già definita per d, // solleva DuplicateException; se d e c // solleva NullPointerException; se d e c // non sono dello stesso tipo di dominio // e codominio solleva ClassCastException. }
Implementazione Si utilizzano due variabili (di tipo class) che memorizzano il tipo del dominio e il tipo del codominio(inizializzate dal costruttore). Per rappresentare la funzione si utilizza un vettore di coppie (argomento, valore). Esempio: {((x1, f(x1)),((x2, f(x2)),… }. Per le coppie usiamo il tipo Pair (di Object, lo omettiamo)
Classe PolyFun public class PolyFun { // OVERVIEW: un PolyFun è una funzione // parziale(a dominio finito) da un tipo // qualunque a qualunque altro. Non è // modificabile. Dominio e codominio // devono essere omogenei. private Vector v; private Class dom; private Class cod;
Classe PolyFun, costruttore // Costruttore public PolyFun (Class dt, Class ct) // EFFECTS: costruisce una nuova PolyFun // avente dominio dt e codominio ct // e indefinita per tutti gli argomenti. {v = new Vector(); dom = dt; cod = ct; }
Classe PolyFun, metodo defined // metodi public boolean defined (Object o) // EFFECTS: se this è definita per // l'argomento o ritorna true altrimenti // ritorna false. for(int i = 0; i < v.size(); i++) { Pair p = (Pair)v.get(i); if (o.equals(p.left()))return true;} return false;}
Classe PolyFun, metodo apply public Object apply (Object o) throws UndefinedException // EFFECTS: se la funzione this è definita // per l'oggetto o restituisce this(o) // altrimenti solleva l'eccezione // (unchecked) UndefinedException. if (!defined(o))throw UndefinedException (“PolyFun.apply”); for(int i = 0; i < v.size(); i++) { Pair p = (Pair)v.get(i); if(o.equals(p.left())) return p.right();} }
Classe PolyFun, metodo bind public void bind (Object d, Object c) throws DuplicateException, ClassCastException, NullPointerException { if (d == null ||c == null) throw NullPointerException(“PolyFun.bind”); if (defined(d)) throw DuplicateException(“PolyFun.bind”); if ( (! dom.isinstance (d) || !cod.isinstance (c) ) throw ClassCastException(“PolyFun.bind”); Pair p = new Pair(c,d); v.add(p); }
Funzione di astrazione Alpha PolyFun (c) = f : c.dom ---> c.cod Tale che f(x) = y sse esiste i, 0 <= i <c.v.size(): c.v.get(i).left() = x c.v.get(i).right() = y
Invariante I PolyFun (c) = per ogni i, 0 <= i <c.v.size() c.v.get(i) non null and c.v.get(i).left().getclass()= c.dom and c.v.get(i).right().getclass()= c.cod and per ogni i, 0 <= i < c.v.size() i != j c.v.get(i).left() != c.v.get(j).left()
Principio di sostituzione Dire se la specifica della seguente sottoclasse di PolyFun soddisfa il principio di sostituzione
Sottoclasse SubPolyFun public class SubPolyFun extends PolyFun { //OVERVIEW: una SubPolyFun è una // sottoclasse di funzioni parziali a // dominio finito da un sottotipo di // oggetti Comparable a un tipo // qualunque. Il dominio e’ ordinato in base a compareTo
SubPolyFun, costruttore // costruttore public SubPolyFun (Comparable d, Object c ) // EFFECTS: costruisce una nuova // SubPolyFun che ha come dominio il tipo di d // e come codominio il tipo di c indefinita // per tutti gli argomenti
SubPolyFun, bind // metodo overriden public void bind (Object d, Object c) throw DuplicateException, ClassCastException // REQUIRES: d deve essere un sottotipo di // Comparable. //MODIFIES:this // EFFECTS: modifica this aggiungendo il legame // tra d e c. Se this è // già definita per d, solleva // DuplicateException; se d e c non sono dello // stesso tipo di dominio e codominio solleva // ClassCastException. Gli elementi di d sono // mantenuti in ordine crescente // rispetto all’ordinamento.
Sottoclasse Le proprieta’ dei dati (OVERVIEW) rafforzate Costruttore della sottoclasse diverso Pre e Post Condizioni di bind modificate Soddisfa il principio di sostituzione?
Notiamo che Post_sub =====> post_super Inserire in modo ordinato e’ piu’ forte che inserire in ordine arbitrario Pre_super =====> pre_sub NON VALE Il metodo del supertipo soddisfa post per qualsiasi parametro Quello del sottotipo solo per d Comparable Non si puo’ rafforzare la precondizione
Domanda Si puo’ modificare la specifica del metodo bind della sottoclasse in modo da risolvere il problema? Togliere la precondizione====> usare le eccezioni per rigettare un parametro non Comparable
Modifica della Specifica // metodo overriden public void bind (Object d, Object c) throw DuplicateException, ClassCastException //MODIFIES:this // EFFECTS: modifica this aggiungendo il legame // tra d e c. Se this è // già definita per d, solleva // DuplicateException; se d e c non sono dello // stesso tipo di dominio e codominio solleva // ClassCastException. Se d non e’ sottotipo di Comparable solleva ClassCastException.Gli elementi di d sono // mantenuti in ordine crescente // rispetto all’ordinamento.
Ora Post_sub=====> Post_super Se d non e’ sottotipo di Comparable solleva ClassCastException =============> Il metodo della superclasse comunque solleva l’eccezione quando controlla se d e’ omogeneo Con il dominio che e’ Comparable
Implementazione Per esercizio In questo caso per mantenere l’ordine bisognerebbe mettere il vettore della superclasse
SubPolyFun, copy // metodi extra public SubPolyFun copy ( ) // EFFECTS: restituisce una copia della // funzione this
SubPolyFun, update public void update (Comparable d, Object c) throws ClassCastException, UndefinedException // MODIFIES: this // EFFECTS: modifica this così da // restituire il valore c, // se applicata a d ; se c non è dello // stesso tipo del codominio di this solleva // ClassCastException, se this non è // definita per d solleva UndefinedException.