LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione...

23
LIP: 1 Marzo 2005 Classe Object e Vettori

Transcript of LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione...

Page 1: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

LIP: 1 Marzo 2005

Classe Object e Vettori

Page 2: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Partiamo da

• L’esercizio dell’ultima esercitazione realizzato tramite array

• Vedremo come si puo’ fare in modo piu’ efficiente usando un nuovo tipo di dato (Vector)

Page 3: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Classe Object

• La classe Object è la superclasse, diretta o indiretta, di ciascuna classe in Java, quindi Object è supertipo di qualsiasi tipo (che definisce oggetti).

• Grazie al meccanismo dell'ereditarietà i suoi metodi sono ereditati da tutti i tipi (che

definiscono oggetti). ad una variabile di tipo Object possiamo assegnare

oggetti di qualsiasi tipo (principio di sostituzione)

Page 4: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Attenzione

• I tipi primitivi int, boolean, double non sono sottotipi di Object, non sono oggetti (vedi la differenza nella semantica di FP)

• String, Integer sono esempi di tipi primitivi

sottotipi di Object• Abbonato, Elenco sono esempi di tipi non primitivi

sottotipi di Object

Page 5: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

•Sono metodi ereditati da tutti i sottotipi

•I metodi più utili sono:

public String toString() { \\EFFECTS: restituisce una rappresentazione dell'oggetto this in forma di stringa. }

public boolean equals(Object obj) \\EFFECTS :verifica se l'oggetto this è uguale a obj.

Metodi Eredidati da Object

Page 6: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Commenti a toString()

•La definizione del metodo nella classe Object restituisce una stringa che contieneil nome della classe dell'oggetto su cui il metodo è invocato ed unarappresentazione esadecimale del codice hash dell'oggetto (indirizzo in memoria dell'oggetto).

•Questo accade perché la classe Object non può conoscere la struttura dell'oggetto.

•Il metodo ereditato e’ poco utile.

•Il metodo deve quindi essere sovrascritto in ogni classe che lo usa per ottenere un risultato significativo. Tipicamente, di un oggetto si vogliono mostrare (nella stringa restituita) i valori delle variabili d'istanza o comunque una informazione significativa che descriva lo stato interno

Page 7: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Commenti ad •Concettualmente, l'invocazione <obj1>.equals(<obj2>) del metodo equals dovrebbe restituire true quando il contenuto dei due oggetti è uguale (non il riferimento, come per l'operatore ==).

•L'esempio tipico è il confronto tra stringhe.

•D’altra parte il metodo equals della classe Object, e’ implementatonon potendo fare alcuna assunzione sulla struttura interna degli oggetti su cui viene invocato (utilizza semplicemente l'operatore == per confrontarli.)

•Deve quindi essere sovrascritto in modo opportuno nel sottotipo (overriding) a seconda delle caretteristiche degli oggetti

•Per il tipo String il metodo e’ gia’ ridefinito in modo primitivo

equals

Page 8: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Metodo equals •Notiamo che il parametro del metodo equals ha tipo Object

•Lo possiamo chiamare su oggetti di ogni tipo (come String ) proprio grazie al principio di sostituzione

•Il confronto con == va bene solo per testare se un oggetto ha riferimento null

Page 9: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Tipo

• La classe java.util.Vector definisce degli oggetti, chiamati vettori (Vector), che consentono di rappresentare sequenze di oggetti di lunghezza variabile.

• Simili agli array a parte il fatto che

-la dimensione di un vettore può variare durante

l'esecuzione di un programma

- non vanno creati per un tipo prefissato, le posizioni del Vector hanno un tipo generico Object

-quindi possono contenere oggetti di ogni tipo anche tra loro disomogenei (tipo String o Integer)

Vector

Page 10: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Costruttori e Metodi (alcuni)

public Vector (){\\EFFECTS: crea un vettore vuoto}

• Notate che a differenza che per gli arrays non e’ necessario fissare al momento della creazione la dimensione

• Ci sono anche altri costruttori tipo quelli degli arrays che permettono di creare un vettore vuoto ma con una certa capacita’ (dato numero di posizioni allocate ma vuote). Serve solo per avere implementazioni piu’ o meno efficienti (per ora lo ignoriamo)

Page 11: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

public int size (){\\EFFECTS: restituisce il numero di elementi presenti nel

vettore}

public Object elementAt (int index){\\EFFECTS: restituisce l'elemento di indice index }

public void setElementAt (Object obj, int  index){\\EFFECTS:

sostituisce obj all'oggetto della posizione index}

• Se index e’ fuori dal size del vettore viene sollevata una eccezione come per gli arrays

Metodi simili a quelli dell’array

Page 12: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

 public void insertElementAt (Object obj, int index){\\MODIFIES:this \\EFFECTS: inserisce obj nella posizione index e sposta tutti gli elementi, da index in poi, di una posizione}

public void addElement (Object obj){\\MODIFIES:this\\EFFECTS: aggiunge una posizione alla fine che contiene obj }

public void removeElementAt (int index){\\MODIFIES:this\\EFFECTS: rimuove l'oggetto presente nella posizione index e spostaall'indietro di una posizione tutti gli elementi successivia quello rimosso}public boolean removeElement (Object obj){\\MODIFIES:this\\EFFECTS: rimuove la prima occorrenza

dell'oggetto obj se presente restituendo true,oppure  restituisce false}

Metodi per rimuovere e aggiungere

Page 13: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Differenze con gli Arrays

• Rifate l’esercizio dell’ Elenco di abbonati usando un Vector invece diun array• Lo stato interno di un oggetto di tipo Elenco e’ descritto da un Vector

di Abbonato (invece che da un array)

public Vector persone; // variabile d’istanza

• Essendo Abbonato sottotipo di Object possiamo usare un Vector per memorizzare abbonati (per esempio per aggiungere)

persone.addElement(new Abbonato(12,15))

Page 14: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Attenzione

•quando usiamo i metodi della classe Vector restituiscono valori di tipo Object. Cosa succede se vogliamo leggere il nome del primo Abbonato del Vector?

// accesso alla variabile d’istanza di Abbonato che memorizza il nome int n= persone.elementAt(1).nome;

•Il compilatore non puo’ sapere quale tipo di valori sono correntemente memorizzati nella prima posizione del Vector, quindi guarda il tipo restituito dal metodo•elementAt e’ un metodo che restituisce un valore di tipo Object, quindi rileva un erroredi tipo (Object non ha una variabile d’istanza nome)

Page 15: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Quindi

•quando usiamo i metodi della classe Vector bisogna usare cast opportuni

Abbonato a= (Abbonato) persone.elementAt(1); a.nome…….// accesso alla variabile d’istanza (senza il cast darebbe un errore)

•In questo modo possiamo aggirare il problema della differenza tra tipo effettivo (Abbonato)e tipo apparente (Object)

Page 16: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Commenti

• Nel momento in cui cambiate l’implementazione del tipo di dato Elenco

deve essere rifatto il programma che il testing?

• Dipende da come lo avete fatto (se accedeva alla variabile d’istanza persone di tipo array della classe Elenco ..chiaramente non va piu’ bene)

• Per esempio si poteva verificare la dimensione corrente dell’array per testare i metodi definiti

Elenco e=new Elenco();System.out.println(e.persone.length);e.inserisci(12);

System.out.println(e.persone.length);

Page 17: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Commenti

• Notiamo che il metodo di testing puo’ accedere alla variabile d’istanza persona perche’ questa e’ public

• Questo suggerisce che non e’ una buona pratica di programmazione rendere visibili le variabili che implementano lo stato interno di un tipo di dato

• Infatti se l’utente del tipo di dato (p.e. Elenco) puo’ accedere alle variabili d’istanza che lo implementano tutto il codice diventa dipendente dalla implementazione del tipo di dato

• Quando l’implementazione del tipo di dato dovesse (come tipicamente sara’) essere migliorata-modificata tutto il codice che la usa e che dipende dall’implementazione dovra’ essere riscritto

• Come succede in questo caso col metodo di testing• E’ fondamentale invece (come vedremo) rendere le varie parti indipendenti

dalla loro implementazione interna usando il piu’ possibile specificatori di accesso private

Page 18: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Sulla implementazione di Elenco

• Per quelli che se la sentono (tipo che hanno gia’ finito l’esercizio dell’altra volta) potete fare una implementazione un po’ piu’ efficiente

• Usando un Vector in cui gli Abbonati sono mantenuti in modo ordinato rispetto al loro nome (come in un elenco del telefono vero)

• In tale caso i metodi di ricerca, inserimento e rimozione devono essere fatti in modo da mantenere l’ordinamento e da sfruttarlo

Per Esempio

Se gli Abbonati sono ordinati in base al nome per cercare un certo Abbonato non dovremo sempre scorrere tutto il vettore

Page 19: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Classe Elenco 1import java.util.*;import java.io.*;

public class Elenco{public Vector persone; // variabile d’istanza public static int numero=1;

// costruttorepublic Elenco(){persone=new Vector();}}

•Lo stato interno di un oggetto di tipo Elenco e’ descritto da un Vector persone•Le variabili d’istanza devono essere inizializzate dal costruttore (invocato per creareun nuovo oggetto)•persone viene inizializzato al vettore vuoto tramite il costruttore di Vector new Vector();

•Se non creiamo il vector il riferimento rimane null non possiamo farci nulla!

Page 20: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Classe Elenco 2\\metodi

public int cercanum(int s){for (int j=0; j< persone.length;j++){Abbonato a =(Abbonato) persone.elementAt(j);if (a.nome==s){return a.num;}}return 0;}public void inserisci(int s){persone.addElement(new Abbonato(s,numero));numero=numero+1;}}

•Quando leggiamo dal Vector dobbiamo fare il cast (anche se sappiamo che contieneoggetti di tipo Abbonato, il compilatore non lo puo’ sapere).•Il metodo addElement aggiunge in fondo al vettore (crea una nuova posizione)•Per aggiungere un nuovo Abbonato dobbiamo fare new Abbonato() per creare il nuovo oggetto

Page 21: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

public class Elencoext extends Elenco{

public Elencoext(){}

public void rimuovi(int s){int j=0;while (j< persone.size()){Abbonato a= (Abbonato) persone.elementAt(j);if (a.nome==s){persone.removeElementAt(j);}else {j++;}}}}

Sottoclasse

•Il metodo removeElementAt elimina una posizione (non lascia una posizione null)

Page 22: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Testerpublic class Tester{public static void main(String[] args){Elenco e=new Elenco();e.inserisci(112);int k=e.cercanum(112);System.out.println(k);int h=e.cercanum(113);System.out.println(h);e.inserisci(113);int t=e.cercanum(113);System.out.println(t);Elencoext y= new Elencoext();y.inserisci(112);y.inserisci(112);int r=y.cercanum(112);System.out.println(r);System.out.println(y.persone.size());y.rimuovi(112);System.out.println(y.persone.size());

}}

Page 23: LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.

Commenti

• La gestione di dati modificabili e’ notevolmente piu’ semplice rispetto agli arrays (automaticamente vengono aggiunte o tolte posizioni)

• Per contro bisogna fare attenzione ai sottotipi ed usare cast per risolvere i problemi del compilatore