Title: Esercizi
1Esercizi
2- Progettare specifica ed implementazione (e
relativa invariante ed astrazione) del tipo di
dato Multiset, multiinsieme di dati del medesimo
tipo. In aggiunta al costruttore si abbiano come
operazioni primitive inserimento, rimozione,
ricerca. - Insieme collezione di elementi, non esiste il
concetto di numero di occorrenze (Ex. 1,7,8) - Multiinsieme collezione di elementi, che possono
occorrere zero o piu volte (Ex. 1,7,8,7,1,1).
Le operazioni aggiungono e rimuovono una
occorrenza
3Si progetti poi il tipo di dato MaxMultiset che
estende Multiset fornendo un metodo che ritorna
il valore che rappresenta la massima molteplicitÃ
degli elementi del multiinsieme. 1,1,3,5,5,5
e 3 Provare che i metodi realizzati soddisfano
l'invariante e la loro specifica. Discutere il
principio di sostituzione
4Specifica Multiset
public class Multiset //OVERVIEW un Multiset
e' un insieme di elementi omogenei in //cui ogni
elemento puo' occorrere piu' volte, es.
1,5,4,1,4. //E' modificabile //metodi public
Multiset () //EFFECTS inizializza this al
multiinsieme vuoto public int isin(Object x)
//EFFECTS restituisce il numero di occorrenze
di x (0 se non compare)
5Specifica
public void insert(Object x) throws
NullPointerException, ClassCastException
//EFFECTS se x e' null solleva
NullPointerException, se x non e'
omogeneo //agli elementi di this solleva
ClassCastException, altrimenti inserisce
unoccorrenza di x in this //MODIFIES
this public void remove(Object
x) //EFFECTS rimuove una occorrenza di x da
this //MODIFIES this
6Specifica
- public Iterator elements()
- //EFFECTS restituisce un generatore che
restituisce - //gli elementi di this, fornendo per ogni
elemento, el - //ed il numero di occorrenze
- Si vuole che restuisca (1,3) se appaiono 3
occorrenze di 1, e non 1, 1, 1 - Tipo ausiliario Pair
7Implementazione
- La scelta fondamentale e quella della
rappresentazione - deve permettere di implementare i metodi in modo
efficiente - Deve permettere la definizione di sottoclassi
(possibilmente senza rende accessibile la
rappresentazione)
8Una possibilita
- Utilizzare un vettore come per linsieme
- Differenza occorrenze multiple
- Non molto efficiente metodo IsIn
- 1,6,8,6,8,1,1 rappresenta 1,6,8,6,8,1,1
9Implementazione
- Vettore di coppie (valore, numero di occorrenze)
- Tipo record ausiliario Pair, due variabili
distanza left e right di tipo Object e int, che
contengono loggetto ed il numero di occorrenze
(molteplicita) - Piu efficiente isIn (rispetto al caso in cui
inserisco gli elementi direttamente nel vettore)
10Insieme omogeneo
- Manteniamo in una variabile di tipo Class il tipo
del primo oggetto inserito (si usa getClass()) - Nota una variabile di tipo Class prende come
valori tutti I tipi (gli posso assegnare
direttamente Integer, Stringvedi costruttore che
prende il tipo)
11La rappresentazione
- public class Multiset
- //OVERVIEW un Multiset e' un insieme di elementi
omogenei in - //cui ogni elemento puo' occorrere piu' volte,
es. 1,5,4,1,4. - //E' modificabile
- private Vector els
- private Class type
- La variabile type memorizza il tipo
- Il vettore els memorizza le coppie
- Quali devono essere le loro proprieta ?
- L invariante esprime le proprieta delle due
variabili distanza - che servono a garantire la correttezza
12Invariante
IMultiset(c) c.els ? null
(c.els.size()gt0 ? c.type ? null)
?i,j 0 ? i?j lt c.els.size() (
c.els.get(i) e un Pair
c.els.get(i).left.getClass()c.type
c.els.get(i).rightgt0
c.els.get(i).left ? c.els.get(j).left
- Le ultime condizioni vietano casi tipo
(a,3),(b,1),(b,3) o (c,0) - Rendono limplementazione piu efficiente
13Funzione di astrazione mappa in multiinsiemi
aMultiset(c) S tale c.els.get(i).left occorre
c.els.get(i).right volte in S
?i0?iltc.els.size()
- mappa un MultiSet in un multiinsieme
- (a,3),(b,1)------gt a,a,a,b
14Metodi
public Multiset () //EFFECTS inizializza this
al multiinsieme vuoto elsnew
Vector() public int isIn(Object
x) //EFFECTS ritorna il numero di occorrenze di
x in //this, eventualmente o if (xnull
return 0 for (int i0 iltels.size() i)
Pair q(Pair) els.get(i) if
(x.equals(q.left)) return q.right
return 0
15Correttezza
- Soddisfano linvariante (banale)
- Soddisfano la specifica?
- Notiamo per isIn sono necessarie le proprieta
dellinvariante, che garantisce che non ci siano
situazioni tipo (a,3),(b,1),(b,3) - Altrimenti potrebbe riportare per b una sola
occorrenza
16Insert 1
- public void insert(Object x)
- throws NullPointerException, ClassCastException
- //EFFECTS se x e' null solleva
NullPointerException, se x non e' omogeneo - //agli elementi di this solleva
ClassCastException, altrimenti inserisce
unoccorrenza di x in this - //MODIFIES this
- if (xnull)
- throw NullPointerException(" ")
- if (els.size()0)
- typex.getClass()
- else
- if (!type.isinstance(x))
- throw ClassCastException(" ")
- poi inserisce
- Prima effettua la verifica del tipo, se e vuoto
inizializza il tipo con quello di x, tramite
getclass - Preserva linvariante (per quanto riguarda
lomogeneita) - Solleva leccezione in accordo alla specifica
17Insert 2
- .
- if (isin(x)0)
- Pair pnew Pair(x,1)
- els.add(p)
- else
- for (int i0 iltels.size() i)
- Pair q(Pair) els.get(i)
- if (x.equals(q.left))
- q.right
-
- Preserva linvariante e soddisfa la specifica
- Inserisce lelemento rispettando i vincoli
dellinvariante - Se non cera crea una nuova coppia
- Altrimenti aggiorna la molteplicita nella coppia
che manteneva - le occorrenze di x
18Remove
- public void remove(Object x)
- //EFFECTS rimuove un'occorrenza di x da this
- //MODIFIES this
- if (isin(x)0) return
- for (int i0 iltels.size() i)
- Pair p(Pair) els.get(i)
- if (x.equals(p.left))
- p.right-- if (p.right0)
- els.remove(i)
19Commenti a remove
- Preserva linvariante e soddisfa la specifica
- Elimina lelemento rispettando i vincoli
dellinvariante - Se cera decrementa il numero di occorrenze
- Se sono zero rimuove proprio la coppia
- Linvariante non ammette (a,0) (piu
efficiente)
20Classe Multiset, Iterator elements
- public Iterator elements()
- //EFFECTS restituisce un generatore che produce
gli elementi // del multiinsieme this nella forma
di coppie //(elemento,molteplicita') - return new MultisetGen(this)
- Literatore e facile da progettare perche la
- rappresentazione e adeguata
21Classe MultisetGen
- private static class MultisetGen implements
Iterator - //OVERVIEW restituisce come Pair tutte le coppie
(element0, // molteplicita) del multiinsieme che
le viene passato - private Multiset set \\ il multinsieme
- private int current \\ prossimo elemento
- //metodi
- public MultisetGen(Multiset m)
- //EFFECTS inizializza set a m e current a 0
- setm current0
-
22Classe MultisetGen
- public boolean hasnext()
- //EFFECTS se ci sono ancora elementi nel
multiinsieme // da generare ritorna true,
altrimenti false - return (currentltset.els.size())
- public Object next() throws NoSuchElementExcepti
on - //EFFECTS restituisce il prossimo elemento del
- // multiinsieme se ce ne sono, altrimenti solleva
- // un'eccezione
- if (currentset.els.size())
- throw NoSuchElementException int
loccurrent - current return set.els.get(loc)
-
23Funzione di astrazione e invariante
aMultisetGen(c) c.set.els.get(current),
..,c.set.els.get(c.set.els.size()-1)
IMultisetGen(c) 0 ? c.current lt
c.set.els.size()
24Sottoclasse
- Estende col metodo maxmul, ritorna la
molteplicita massima presente nellinsieme - Si puo implementare col generatore (ad ogni
chiamata scorre gli elementi e trova il massimo) - Si puo mettere una variabile distanza e
mantenerla aggiornata (tramite loverriding di
insert e remove)
25In ogni caso
- La rappresentazione della superclasse e
mascherata - Vantaggio il codice delle sottoclassi e
indipendente da quello della superclasse - Facciamo vedere la seconda soluzione sfrutta la
gerarchia
26Classe MaxMultiset, metodo maxmul
- public class MaxMultiset extends Multiset
- //OVERVIEW un MaxMultiset e' un Multiset che
mantiene traccia della massima molteplicita' dei
suoi elementi - private int max
- //metodi
- public MaxMultiset ()
- //EFFECTS inizializza this al MaxMultiSet vuoto
- super() max0
- public int maxmul()
- //EFFECTS restituisce il valore della
molteplicita' massima - return max
27Overriding di Insert
- public void insert (object x)
- throws NullPointerException, ClassCastException
- //EFFECTS aggiunge una occorrenza di x in this
- //MODIFIES this
- super.insert(x) int numeroisIn(x) if
(numerogtmax) maxnumero -
- Aggiorna il massimo (lelemento inserito
- potrebbe avere ora la molteplicita max)
- Le post condizioni sono uguali
28Overriding di Remove
- public void remove (object x)
- //EFFECTS rimuove una occorrenza di x da this
- //MODIFIES this
- int numeroisIn(x)
- super.remove(x) if (numero lt max) return else
aggiornamax()
- Le post condizioni sono uguali
- Se x aveva il numero max di occorrenze,
- lo devo ricalcolare
29Classe MaxMultiset, metodo aggiornamax
- private void aggiornamax()
- //EFFECTS aggiorna la molteplicita' massima
- //MODIFIES this
- max0
- Iterator g elements()
- while (g.hasnext())
- Pair p (Pair)g.next()
- if (p.right()gtmax)
- max p.right
-
-
30Funzione di astrazione e invariante
- aMaxMultiset(c) aMultiset(c)
- IMaxMultiset(c)
- c.max ? 0
- c.maxgt0? ?x?aMultiset(c)x occorre c.max volte
- ?x?aMultiset(c) la molteplicita' di x e' ? c.max
- E linvariante della superclasse?
31Commenti
- Nel progetto della superclasse deve essere
previsto come si puo estendere (accesso diretto
o metodi) - Abbiamo fornito il generatore alle possibili
sottoclassi per mantenere la rappresentazione
privata - Alternativa rappresentazione della superclasse
protected (accesso diretto) - Piu efficiente, ma la sottoclasse diventerebbe
dipendente dallimplementazione della superclasse - Inoltre la correttezza sarebbe piu complessa la
sottoclasse potrebbe invalidare la correttezza
della superclasse (potrebbe violarne linvariante)
32Consiglio
- Le soluzioni migliori (piu efficienti e\o ben
strutturate) sono piu complicate piu
condizioni nellinvariante, nei metodi bisogna
fare attenzione a piu proprieta (per esempio a
non inserire (a,8),(a,1)) - Cercate di non scegliere la via piu facile
solo per fare prima
33Altro Esercizio
- Problema vogliamo progettare un tipo di dato
Lista Ordinata Generica - In grado di memorizzare interi, stringhe etc,
ognuno con il relativo ordinamento - Bisogna essere parametrici rispetto al tipo degli
elementi e anche rispetto alla relativa - nozione di ordinamento
- Due approcci basati sulluso delle interfacce
34Primo Approccio element subtype
- definiamo linterfaccia I che definisce le
proprietà richieste (in questo caso
lordinamento), Comparable - definiamo il tipo di dato (in questo caso la
lista) con elementi di tipo I (Comparable) - definiamo gli oggetti come sottotipi
dellinterfaccia I
35La classe OrderedList
- Generalizza OrderedIntList
- Permette di definire liste piu generali, che
hanno come elementi, sottotipi dellinterfaccia
Comparable - specifica e implementazione simili a quelle di
OrderedIntList solo che - argomenti e risultati delle operazioni sono
Comparable invece che int - lordinamento è fatto usando compareTo
36La classe OrderedList
- Possiamo usarlo solo per memorizzare liste
ordinate di elementi sottotipi di Comparable,
ovvero che implementano linterfaccia fornendo il
metodi compareTo - String, Integer
- Nuovi tipi predefiniti
37Esempio
- Supponiamo di volere mantenere ordinate delle
coppie di interi - Ordinamento richiesto in modo crescente in base
al primo elemento, se il primo elemento e uguale
in base al secondo in ordine crescente - Ex (1,2),(1,3),(2,1,),(2,4),(4,1)
38Per usare OrderedList
- E pero necessario definire a priori le coppie
di interi come sottotipo di Comparable - public class IPair implements Comparable
- //OVERVIEW sono coppie di interi su cui e
definito un ordine // totale - public int left \\ il primo elemento
- public int right\\ il secondo elemento
- public IPair(int x,int y)rightx,lefty
- public int compareTo (Object x) throws
ClassCastException, NullPointerException - .verifica se this e minore o uguale o
maggiore di x secondo - lordinamento descritto in precedenza
tra coppie -
39Per usare OrderedList
- public int compareTo (Object x) throws
ClassCastException, NullPointerException - IPair y(IPair) x
- if (left lt x.left) return -1
- if (x.left lt left) return 1
- else
- if (right lt x.right) return -1
- if (x.right lt rigth) return 1
- return 0
40Esempio di uso
- IPair p new IPair (1,3)
- IPair qnew IPair (2,4)
- OrderedList lnew OrderedList()
- l.add(p) l.add(q)
- l.toString()
- Ritorna la lista ordinata (come String)
(1,3),(2,4) - I metodi di OrderedList usano compareTo per
ordinare gli oggetti, in questo caso quello
fornito dal tipo di dato IPair
41Svantaggi
- Definendo il tipo IPair come sottotipo di
Comparable le coppie hanno direttamente la
relativa operazione di ordinamento (implementata
da compareTo) - E se avessi gia definito un tipo Pair che
rappresenta le coppie di interi ma non implementa
Comparable? - Si puo definire un tipo di dato polimorfo
OrderedList che funziona anche per tipi
pre-esistenti?
42Alternativa OrderedList
- Ha come elementi Object
- Il confronto e fatto usando il metodo compare,
fornito da una interfaccia Comparator (anche
questa pre-definita in Java) - Limplementazione dellinterfaccia viene passata
come parametro al costruttore e memorizzata per
usare la relativa nozione di ordinamento - Per usare la lista per un certo tipo di dato T
basta definire (anche a posteriori)
limplementazione di Comparator relativa a T
43Linterfaccia Comparator
public interface Comparator // OVERVIEW tutti
i sottotipi di Comparator forniscono //metodi per
confontare gli elementi di un tipo //
collegato public int compare (Object x, Object
y) throws NullPointerException,
ClassCastException // EFFECTS se uno tra x o y
è null, solleva // NullPointerException se x e
y non sono // confrontabili solleva
ClassCastException altrimenti, // se x è minore
di y ritorna -1 se y x ritorna 0 //se x è
maggiore di y, ritorna 1
44Come usare OrderedList?
- Vogliamo fare una lista ordinata di Pair
(pre-definito) - Pair non implementa direttamente linterfaccia
- Comparator non hanno incluso lordinamento
- Dobbiamo invece definire un implementazione di
- Comparator, collegata a Pair, che realizza il
confronto - tra coppie (quello richiesto)
- Dobbiamo passare ad OrderedList
- l implementazione di Comparator, collegata a
Pair
45Esercizio
- Definire il sottotipo di Comparator,
PairComparator che realizza il confronto tra le
coppie - Se i parametri passati a compare non sono coppie
deve sollevare ClassCastException, non sono
confrontabili (basta usare il cast)
46public class PairCompator implements Comparator
// OVERVIEW definisce un sottotipo di
Comparator relativo //al tipo Pair public int
compare (Object x, Object y) throws
NullPointerException, ClassCastException
// EFFECTS se uno tra x o y è null, solleva
// NullPointerException se x e y non sono //
confrontabili solleva ClassCastException
altrimenti, // se x è minore di y ritorna -1 se
y x ritorna 0 //se x è maggiore di y, ritorna
1 if (xnull ynull) throw new
NullPointerException() Pair p1 (Pair) x Pair
p2(Pair) y if (p1.left lt p2.left) return -1
if (p1.left lt p2.left) return 1 else if
(p1.right lt p2.right) return -1 if (p1.right
lt p2.rigth) return 1 return 0
47Specifica di OrderedList
public class OrderedList // OVERVIEW e una
lista modificabile ordinata // e omogenea di
Object. // Oggetto tipico x1, . . . , xn con
xi lt xj se // i lt j. Il confronto fra gli
elementi è // effettuato con il metodo compare
di una // interfaccia Comparator relativa //
costruttore public OrderedList (Comparator c )
// EFFECTS inizializza this alla lista //
ordinata vuota che ha elementi del tipo
//collegato c
48Specifica di OrderedList 2
// metodi public void addEl (Object el)
throws NullPointerException, DuplicateException,
ClassCastException // MODIFIES this //
EFFECTS se el è in this, solleva
//DuplicateException se el è null solleva
//NuIlPointerException se el non è confrontabile
//con gli altri elementi in this solleva
//ClassCastException altrimenti, aggiunge el a
this public void remove (Object el) //
MODIFIES this // EFFECTS se el è in this, lo
rimuove altrimenti, //non fa nulla
49Specifica di OrderedList 2
// metodi public Object first() throws
EmptyException // EFFECTS se el è vuota
solleva EmptyException, altrimenti restituisce il
primo elemento public OrederedList next()
throws EmptyException // EFFECTS se el è
vuota solleva EmptyException, altrimenti
restituisce resto della lista public boolean
IsIn (Object el) // EFFECTS se el è in this
restituisce true, //altrimenti false
50Implementazione
public class OrderedList private Object
val private boolean vuota private OrderedList
next private Comparator conf public
OrderedList (Comparator c ) vuotatrue
confc
51Invariante e funzione di astrazione
- Funzione di astrazione la solita
- Invariante
- I(c) c.conf!null e
- !c.vuota gt
- (c.next e c.val!null e
- c.conf.compare(c.val,c.val) non
solleva ecc. e - c.confc.next.conf e I(c.next) e
- c.conf.compare( c.val,c.next.val ) lt0
- )
52Implementazione
public void addEl (Object el) throws NullPointerEx
ception,DuplicateException, ClassCastException
if (elnull) throw new NullPointerException(
) if (vuota)int nconf.compare(el,el) valel
vuotafalse nextnew OrderedList(conf) else in
t nconf.compare(val,el) if (n0) throw new
DuplicateException() if (n lt0)
next.addEl(el) else OrderedList lnew
OrderedList(conf) l.valvall.vuotavuota l.next
next l.confconf valelnextl
53Implementazione
public void remove (Object el) if (vuota)
return int nconf.compare(val,el) if (n0)
if (next.vuota) vuotatrue else valnext.val
vuotanext.vuota nextnext.next else
next.remove(el)
54Implementazione di OrderedList
public Object first() throws EmptyException
if (vuota) throw new Emptyexception(first)
return val public OrederedList next() throws
EmptyException if (vuota) throw new
Emptyexception(first) return next public
boolean IsIn (Object el) if (vuota) return
false in n conf.compare(val,el) if
(n0) return true else return
next.IsIn(el)
55Differenza rispetto allaltro metodo
- Per confrontare el con lelemento del vettore
chiama il metodo compare del Comparator - int nconf.compare(o,el)
- Per confrontare el con lelemento del vettore
chiama il metodo compareto sullelemento (sono
Comparable) - int no.compareto(el)
- Nel primo approccio gli elementi non hanno
direttamente il metodo di confronto (glielo passo
col Comparator relativo) - Nel secondo approccio gli elementi hanno
direttamente il metodo di confronto (implementano
Comparable)
56Differenza nelluso
IPair p new IPair (1,3) //sottotipo di
Comparable IPair qnew IPair (2,4) OrderedList
lnew OrderedList() l.add(p) l.add(q) //ordina
con compareTo l.toString() Pair p new Pair
(1,3) Pair qnew Pair (2,4) OrderedList lnew
OrderedList(new PairComparator()) l.add(p)
l.add(q) //ordina con compare l.toString() Ritor
na la lista ordinata (come String) (1,3),(2,4)