LIP 9 Maggio 2006 Esercizi Riprendiamo un esercizio

  • Slides: 34
Download presentation
LIP: 9 Maggio 2006

LIP: 9 Maggio 2006

Esercizi • Riprendiamo un esercizio proposto • Definire un tipo di dato Persona che

Esercizi • Riprendiamo un esercizio proposto • Definire un tipo di dato Persona che definisce oggetti che rappresentano le informazioni relative ad una persona, • Nome (String), Data di Nascita (int) , Indirizzo (String)

Specifica ed Implementazione public class Persona{ \OVERVIEW: una Persona memorizza informazioni relative al nome,

Specifica ed Implementazione public class Persona{ \OVERVIEW: una Persona memorizza informazioni relative al nome, data di nascita, indirizzo private String nome; private int data; private String ind; public Persona(String n, int x, String i){ \EFFECTS: costruisce una nuova Persona con nome n, data di nascita x ed indirizzo i nome=n; data=x; ind=i; }

Metodi Osservatori public String getnome (){ \EFFECTS: resituisce il nome di this return nome;

Metodi Osservatori public String getnome (){ \EFFECTS: resituisce il nome di this return nome; } public int getdata (){ \EFFECTS: resituisce la data di nascita di this return data; } public String getind (){ \EFFECTS: restituisce l’indirizzo return ind; } di this NECESSARI per leggere i valori dei campi che descrivono persona pur mantenendo la rappresentazione mascherata

Specifica public String to. String() (){ \EFFECTS: restituisce una descrizione di this return “nome:

Specifica public String to. String() (){ \EFFECTS: restituisce una descrizione di this return “nome: ” + nome + “data: ” + data + “indirizzo: ” + ind; } public boolean equals(Object o) (){ \EFFECTS: se o non e’ di tipo Persona solleva Class. Cast. Exception, altrimenti restituisce true sse this ed o sono uguali Persona p =(Persona) o; if (nome. equals (p. nome) && data==p. data && ind. equals (p. ind)) {return true; } else {return false; }} public void change (String x){ \MODIFIES: this \EFFECTS: assegna a this il nuovo indirizzo x ind=x; } }

Sottotipi • Definire la specifica e l’implementazione di due sottotipi di Persona • Studente:

Sottotipi • Definire la specifica e l’implementazione di due sottotipi di Persona • Studente: aggiunge l’informazione sul numero di matricola (int) • Professore: aggiunge l’informazione sul corso che insegna (String)

Specifica ed Implementazione • Progettare la specifica: costruttore, metodi aggiuntivi, metodi sovrascritti • Sfruttare

Specifica ed Implementazione • Progettare la specifica: costruttore, metodi aggiuntivi, metodi sovrascritti • Sfruttare la gerarchia cercando di riutilizzare il piu’ possibile il codice • Non accedere alla rappresentazione della superclasse (non usare protected)

public class Studente extends Persona{ \OVERVIEW: uno Studente e’ un sottotipo di Persona che

public class Studente extends Persona{ \OVERVIEW: uno Studente e’ un sottotipo di Persona che aggiunge informazioni sul numero di matricola private int matricola; • Ogni Studente ha 4 variabili d’istanza, i metodi non possono pero’ accedere alle variabili eredidate • Deve inizializzarle tramite i metodi della superclasse (super) • Vantaggio: l’implementazione della sottoclasse e’ indipendente da quella della super private String nome; private int data; private String ind;

public Studente(String n, int x, String i, int m){ \EFFECTS: costruisce un nuovo Studente

public Studente(String n, int x, String i, int m){ \EFFECTS: costruisce un nuovo Studente con nome n, data di nascita x, indirizzo i e matricola m super(n, x, i); matricola=m; } \ metodo nuovo public int getmatricola (){ \EFFECTS: restituisce la matricola return matricola; } di this \ metodi sovrascritti (necessario) public String to. String() (){ \EFFECTS: restituisce una descrizione di this return super. to. String() + “matricola: ” + matricola; } public boolean equals(Object o) (){ \EFFECTS: se o non e’ di tipo Studente solleva Class. Cast. Exception, altrimenti restituisce true sse this ed o sono uguali Studente p =(Studente) o; if (super. equals(p) && matricola==p. matricola) {return true; } else {return false; }}

Seconda Parte • Lista Ordinata di elementi di tipo Persona • Permette di memorizzare

Seconda Parte • Lista Ordinata di elementi di tipo Persona • Permette di memorizzare sia elementi di tipo Studente che di tipo Professore (sia di qualsiasi altro sottotipo di Persona) • Ordinamento: in ordine alfabetico, e quindi secondo la data di nascita Ex: (Andrea, 3) < (Pippo, 1) (Andrea, 1) < (Andrea, 3)

public class Lista. P { // OVERVIEW: `e una lista modificabile //ordinata di oggetti

public class Lista. P { // OVERVIEW: `e una lista modificabile //ordinata di oggetti sottotipo di Persona // Oggetto tipico [x 1, . . . , xn] con xi < xj se i < j // Il confronto fra gli elementi e’ effettuato in base //all’ordinamento spiegato in precedenza private Persona val; private Lista. P next; private boolean vuota; public List. P( ) { // EFFECTS: inizializza this alla lista ordinata vuota=true; }

public void add. El (Persona el) throws Null. Pointer. Exception, Duplicate. Exception { //

public void add. El (Persona el) throws Null. Pointer. Exception, Duplicate. Exception { // MODIFIES: this // EFFECTS: se el è in this, solleva Duplicate. Exception; se el // è null solleva Nu. Il. Pointer. Exception; altrimenti, aggiunge //el a this rispettando l’ordinamento if (el==null) throw new Null. Pointer. Exception(); if (vuota) {val=el; vuota=false; next= new Lista. P(); } else {if (val. equals (el)) new Duplicate. Exception(); int conf= val. get. Nome(). compare. To(el. get. Nome()); if (conf==1 || ((conf==0) && val. get. Data() > = el. get. Data())) // se val precede el deve inserire il nuovo nodo in testa

{ Lista. P nodo=new Lista. P(); nodo. val=val; nodo. vuota=vuota; nodo. next=next; val=el; next=nodo;

{ Lista. P nodo=new Lista. P(); nodo. val=val; nodo. vuota=vuota; nodo. next=next; val=el; next=nodo; } else {next. add. El(el); return; } } }

public Persona first () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva

public Persona first () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, // altrimenti ritorna il minimo (primo) elemento di this if (vuota) {throw new Empty. Exception(“Lista. P. first()”); return val; } public List. P rest () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, //altrimenti ritorna la lista ottenuta da this togliendo // il primo elemento if (vuota) {throw new Empty. Exception(“Lista. P. first()”); return next; } } public int size () { // EFFECTS: ritorna il numero di elementi di this if (vuota) {return 0; } return 1 + next. size(); }

public boolean is. In (String x) { // EFFECTS: restituisce true se una Persona

public boolean is. In (String x) { // EFFECTS: restituisce true se una Persona con nome x // appare in this, false altrimenti if (vuota) {return false; } int conf= val. get. Nome(). compare. To(x); if (conf==0) {return true; } if (conf==1) {return false; } else {return next. is. In(x); } } public String to. String () { // EFFECTS: standard if (vuota) {return “”; } return val. to. String() +next. to. String(); } }

public boolean equals (Lista. P p) { // EFFECTS: restituisce true se this e

public boolean equals (Lista. P p) { // EFFECTS: restituisce true se this e p sono uguali if (size() != p. size()) {return false; } if (vuota && p. vuota) {return true; } if (! val. equals(p. val)) {return false; } else {return next. equals (p. next); } }

Liste Ordinate • Abbiamo visto la realizzazione del tipo di dato astratto Lista Concatenata

Liste Ordinate • Abbiamo visto la realizzazione del tipo di dato astratto Lista Concatenata di Persona • Vantaggio: puo’ essere usata per memorizzare elementi che sono sottotipi, es. Studente e Professore • Svantaggio: l’ordinamento e’ fissato (quello definito per Persona) • Potrebbe essere utile essere parametrici anche rispetto alla nozione di ordine

Esempio • Per Studente si potrebbe usare un ordinamento diverso, in cui a parita’

Esempio • Per Studente si potrebbe usare un ordinamento diverso, in cui a parita’ di nome, gli oggetti vengano ordinati in base al numero di matricola • Bisogna generalizzare il tipo di dato

Liste Ordinate Generiche • Sarebbe meglio avere un tipo di dato OList piu’ generale

Liste Ordinate Generiche • Sarebbe meglio avere un tipo di dato OList piu’ generale che possa essere istanziato per un dato tipo • Parametrico rispetto sia al tipo degli elementi che dell’ordinamento • Vorrei poterlo usare per memorizzare Persona, suoi sottotipi, String, Integer • Ognuno con il suo ordinamento

In Java • Non esistono meccanismi diretti per fare il polimorfismo • Si puo’

In Java • Non esistono meccanismi diretti per fare il polimorfismo • Si puo’ ottenere usando varie tecniche • Oggi ne vedremo una che e’ basata sull’idea di usare l’ereditarieta’ ovvero i sottotipi per realizzare una lista polimorfa • In particolare vedremo come le interfacce possano essere usate per realizzare una forma di lista generica ordinata

Per cominciare a capire • Supponiamo di volere realizzare una lista generica • In

Per cominciare a capire • Supponiamo di volere realizzare una lista generica • In cui gli elementi sono ordinati in ordine crescente • Deve essere parametrica sia nel tipo degli elementi che nel relativo ordinamento • Per esempio: se istanziata con stringhe l’ordinamento sara’ quello lessicografico etc. .

 • Per realizzare una lista generica potrei dire che ha elementi Object •

• Per realizzare una lista generica potrei dire che ha elementi Object • E’ facile modificare la specifica e l’implementazione che abbiamo visto • Non sarebbe garantita l’omogeneita’, ovvero non sarebbe possibile istanziare la lista con un dato Tipo (tipo nel Vector) • Inoltre in Object non esiste un metodo di ordinamento

Interfaccia Comparable (è definito in java. util) –Ha un solo metodo compare. To che

Interfaccia Comparable (è definito in java. util) –Ha un solo metodo compare. To che serve per realizzare confronti –Tutti i sottotipi implementano il metodo compare. To –Fornisce un supertipo i cui sottotipi hanno tutti un metodo per il confronto (relazione di ordinamento totale)

L’interfaccia Comparable public interface Comparable { // OVERVIEW: i sottotipi di Comparable forniscono un

L’interfaccia Comparable public interface Comparable { // OVERVIEW: i sottotipi di Comparable forniscono un metodo // per determinare la relazione di ordinamento fra i loro // oggetti; l’ordinamento deve essere totale e, ovviamente, // transitivo e simmetrico; infine // x. compare. To (y) == 0 implica x. equals (y) public int compare. To (Object x) throws Class. Cast. Exception, Null. Pointer. Exception; // EFFECTS: se x è null, lancia Null. Pointer. Exception; // se this e x non sono confrontabili, solleva Class. Cast. Exception; // altrimenti, se this è minore di x ritorna -1; // se this = x ritorna 0; se this è maggiore di x, ritorna 1 }

Nota • Il metodo compare. To realizza l’ordinamento • Se chiamato su oggetti che

Nota • Il metodo compare. To realizza l’ordinamento • Se chiamato su oggetti che non sono omogenei (tipo String ed Integer) allora solleva Class. Cast. Exception

Uso di Comparable • Facciamo una lista ordinata generica ed omogenea usando Comparable •

Uso di Comparable • Facciamo una lista ordinata generica ed omogenea usando Comparable • Gli elementi della lista sono di tipo Comparable (invece che Integer o String etc…) • Il confronto e’ fatto in modo generico usando compare. To • Questo permette di usare la lista per memorizzare qualsiasi sottotipo di Comparable • Verra’ scelto l’ordinamento giusto in base al tipo degli elementi

Cosa cambia nella Specifica? • Bisogna indicare che gli elementi sono Comparable – argomenti

Cosa cambia nella Specifica? • Bisogna indicare che gli elementi sono Comparable – argomenti e risultati sono Comparable invece che int – bisogna indicare che gli elementi sono ordinati rispetto a compare. To • Ordered. List assicura che gli elementi della lista siano omogenei – Si sfutta il fatto che compare. To solleva un’eccezione se gli oggetti non sono confrontabili • il tipo degli elementi nella lista è determinato dall’inserimento del primo elemento – se la lista diventa vuota il tipo può cambiare con l’aggiunta di un nuovo elemento

Specifica di Ordered. List public class Ordered. List { // OVERVIEW: `e una lista

Specifica di Ordered. List public class Ordered. List { // OVERVIEW: `e una lista modificabile ordinata di // oggetti omogenei di tipo Comparable // Oggetto tipico [x 1, . . . , xn] con xi < xj se i < j // Il confronto fra gli elementi è effettuato con il // metodo compare. To • Nota: xi < xj significa rispetto a compare. To

Costruttori e Metodi public Ordered. List ( ) { // EFFECTS: inizializza this alla

Costruttori e Metodi public Ordered. List ( ) { // EFFECTS: inizializza this alla lista ordinata vuota} public void add. El (Comparable el) throws Null. Pointer. Exception, Duplicate. Exception, Class. Cast. Exception { // MODIFIES: this // EFFECTS: se el è in this, solleva Duplicate. Exception; se el //è null solleva Nu. Il. Pointer. Exception; se el non è //confrontabile con gli altri elementi in this solleva //Class. Cast. Exception; altrimenti, aggiunge el a this} Nota: in questo caso aggiunge vuol dire che lo aggiunge in base all’ordinamento

Specifica public Comparable first () throws Empty. Exception{ // EFFECTS: se this è vuoto

Specifica public Comparable first () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, //altrimenti ritorna il primo elemento di this} public Ordered. List rest () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, //altrimenti ritorna la lista ottenuta da this togliendo il primo elemento} public int size () { // EFFECTS: restituisce il numero di elementi di this} public boolean Is. In(Comparable c) { // EFFECTS: restituisce true se c compare in this, //false altrimenti} public String to. String (){\EFFECTS: standard} }

Testing • Non esistono oggetti di tipo Comparable (interfaccia) • Esistono oggetti che sono

Testing • Non esistono oggetti di tipo Comparable (interfaccia) • Esistono oggetti che sono sottotipi di Comparable • String, Integer (implementazioni dell’interfaccia)

Sottotipi di Comparable • E se volessimo usarlo per memorizzare un sottotipo non primitivo?

Sottotipi di Comparable • E se volessimo usarlo per memorizzare un sottotipo non primitivo? • Es. Persona, Studente, Professore • Vanno modificati, non sono sottotipi di Persona

public class Persona implements Comparable{ \OVERVIEW: una Persona e’ un sottotipo di Comparable, memorizza

public class Persona implements Comparable{ \OVERVIEW: una Persona e’ un sottotipo di Comparable, memorizza informazioni relative al nome, data di nascita, indirizzo ……. . SPECIFICA ED IMPLEMENTAZIONE UGUALE A PRIMA + METODO EREDITATO DALL’INTERFACCIA public int compare. To (Object x) throws Class. Cast. Exception, Null. Pointer. Exception{ // EFFECTS: se x è null, lancia Null. Pointer. Exception; // se this e x non sono confrontabili, solleva Class. Cast. Exception; // altrimenti, se this è minore di x ritorna -1; // se this = x ritorna 0; se this è maggiore di x, ritorna 1}

A casa • Riproggettare le classi Studente e Professore • Dovranno sovrascrivere il metodo

A casa • Riproggettare le classi Studente e Professore • Dovranno sovrascrivere il metodo compare. To di Persona • Per ogni sottotipo possiamo avere un ordinamento relativo, piu’ specifico