Java: tipi (im)mutaibili. Metodi equals e clone

Похожие документы
Uguaglianza e copia di oggetti

La classe java.lang.object

Programmazione 2 - Marco Ronchetti. Fondamenti di Java. Fac.Scienze Università di Trento. Static

A. Lorenzi, A. Rizzi Java. Programmazione ad oggetti e applicazioni Android Istituto Italiano Edizioni Atlas

Corso di Algoritmi e Strutture dati Programmazione Object- Oriented in Java (Parte I)

Fondamenti di Informatica I

Esempio su strutture dati dinamiche: ArrayList

18 - Vettori. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

Esempio su strutture dati dinamiche: ArrayList

Numeri complessi. Definire un ADT Complex in grado di rappresentare un numero complesso. La classe deve essere immutabile.

Riassunto: cos è la OOP? classi astratte, interfacce, classi interne. Scaletta. Figura con area()? Figura senza area()? Stefano Mizzaro 1.

ESERCIZI JAVA. Esercizi sulle Interfacce. Esercizio 1:

Definizione di classi. Walter Didimo

16 - Ereditarietà, tipi e gerarchie

Esempio 2: Subtyping

Polimorfismo parametrico vs polimorfismo per inclusione

Ereditarietà. Ereditarietà. Ereditarietà. Ereditarietà

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

18 - Classi parzialmente definite: Classi Astratte e Interfacce

Le basi del linguaggio Java

Politecnico di Milano

Programmazione orientata agli oggetti. Ivan Lanese

Programmazione Orientata agli Oggetti. Emilio Di Giacomo e Walter Didimo

Laboratorio di programmazione

Programmazione ad oggetti

Implementazione Java di un ADT

14 - Metodi e Costruttori

Linguaggi di programmazione II AA 2010/2011 Esercitazione 2

Programmazione in Java (I modulo)

Synchronized (ancora)

Java Virtual Machine. Indipendenza di java dalla macchina ospite. I threads in Java

Il Linguaggio Java. Le interfacce

Proprietà delle Classi e degli Oggetti in Java

Laboratorio di Programmazione Lezione 4. Cristian Del Fabbro

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

Programmazione con Java

Ricerca e ordinamento su array di oggetti. Corso di Programmazione 2 Esercitazione 5

Capitolo 5 - Funzioni

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Il linguaggio C. Puntatori e dintorni

Esempio su strutture dati dinamiche: ArrayList

In questa lezione. Polimorfismo

Metodi statici. Dichiarazione e chiamata di metodi statici

Fondamenti di Informatica T-1. Classi e metodi astratti

Alberi Binario in Java

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Esercitazione. Docente Ing. Mariateresa Celardo

La fase di progetto e realizzazione. PROGETTAZIONE DEL SOFTWARE (Ing. Gestionale) Diagramma delle classi realizzativo

Laboratorio di Programmazione Lezione 2. Cristian Del Fabbro

Polimorfismo per Genericità in Java

Транскрипт:

Java: tipi (im)mutaibili. Metodi equals e clone Mutabilità Un tipo è mutabile (mutable) se ha dei metodi che possono modificare ilrep, altrimenti è detto immutabile (immutable). della classe! Il metodo è mutator già nella specifica Come decidere fra mutable e immutable? Perché IntSet mutable e Poly immutable? 2 1

Mutable meglio per oggetti che modellano entità del mondo reale: automobili, persone, ecc. che cambiano dinamicamente poco sicuro se oggetti condividono parti, ma efficiente quindi lo usiamo per IntSet perché pensiamo che dovremo spesso mettere o togliere elementi: molto più efficiente se non dobbiamo ad ogni inserzione copiare il contenuto di un IntSet in un nuovo oggetto e Richiede syncronized, lock ecc. per essere thread-safe 3 Immutable Usato sempre se oggetti possono comparire in espressioni, come ad es. oggetti espressioni non hanno side-effect spiacevoli... Es. supponiamo che Poly sia mutabile e add sia così definita: //@ ensures q!=null && (* this == \old(this) + q *); //@ signals (NullPointerException e) q == null; public Poly add(poly q) throws NullPointerException se p = 3x, che cosa vale p dopo p.add(p).add(p)? è come p+p+p? e p.add(p.add(p))? è come p+(p+p)? Da usare se oggetti devono potere condividere parti, o per non usare sync. In programmazione multithread poco efficiente se occorre spesso modificare oggetti: per cambiare un oggetto occorre farne una copia con produttori, con perdita di tempo e appesantimento del garbage collector. Tipicamente, i tipi immutabili sono dichiarati /*@ pure @*/ in JML (ma ciò non basta a garantire immutabilità...) 4 2

Come definire oggetti immutabili Definire tutti gli attributi di istanza final e private però se servono effetti coll. benevoli allora possono non essere final Se gli attributi di istanza hanno riferimenti a oggetti mutabili non esporre le parti mutabili del rep Se si vuole che anche gli oggetti delle sottoclassi restino immutabili, non consentire alle sottoclassi di fare override dei metodi basta dichiarare la classe final 5 Il metodo public Object clone() Il metodo clone() restituisce una copia del suo oggetto, nello stesso stato. clone bitwise copy) ma normalmente clone non è accessibile (protected): se si vuole che classe fornisca clone, occorre scrivere: implements Cloneable e definire un metodo clone (che ad esempio richiama il clone definito in Object), altrimenti chiamata a clone() provoca eccezione CloneNotSupportedException: public class IntSet implements Cloneable{ public Object clone() {return super.clone();} IntSet s = new IntSet(); s.insert(2); IntSet t = (IntSet) s.clone(); //clone restituisce un Object: serve cast clone() può esser definito ad hoc quando la definizione di Object non va 6 3

Quando ridefinire clone()? clone() (se serve usarlo) va ridefinito se la classe è mutabile. Es. IntSet s = new IntSet(); IntSet t = (IntSet) s.clone();s.insert(2); System.out.println(t.toString()); la clone() di default (in Object) copia campo per campo, cioè: t= (IntSet) s.clone(); è come t = new IntSet(); t.els =s.els; Quindi s e t hanno stesso valore per campo els di tipo ArrayList: sharing! Oggetti mutabili non possono condividere parti, pena grossi guai! Implementazione corretta per IntSet: private IntSet(ArrayList v) {els = v;} public Object clone() { return new IntSet((ArrayList) els.clone()); } si basa sul fatto che clone() di ArrayList fa copia elemento per elemento 7 Problemi con clone() di Object e tipi mutabili (shallow copy) paolo p seteta eta = 020 seteta eta = 030 40 seteta eta = 020 p = () paolo.clone(); //usa bitwise clopy //modifiche a p.padre sono modifiche a paolo.padre, anche se paolo e p sono oggetti distinti! 8 4

Differenza con deep copy paolo p seteta eta = 020 seteta eta = 030 40 seteta eta = 020 seteta eta = 030 40 p = () paolo.clone(); //ora usa deep clopy 9 clone() e tipi immutabili Non è invece necessario ridefinire clone se la classe è immutabile! Se classe è immutabile, basta una sola copia dei suoi oggetti Poly p = new Poly(3,2); Poly q = p; q è copia di p, anche se sono condivisi: oggetto riferito da p (e quindi p non può essere cambiato! quindi se clone() serve per tipi immutabili (ad es. perché si richiamano metodi che si aspettano degli oggetti clonabili), basta implementare un metodo che richiama quello predefinito in Object o addirittura che fa copia del reference 10 5

Metodo equals della classe Object -tipi della classe Object, per cui è predefinite le operazioni public boolean equals (Object z) implementazione di default: confronto fra reference: due oggetti sono equals solo se sono lo stesso oggetto dei metodi della classe Object o se è meglio ri-definirli!!! Nel caso di equals occorre una certa Lo standard Java richiede che: public boolean equals(object obj) indicates whether some other object is "equal to" this one. The equals method implements an equivalence relation on non-null object references: It is reflexive: for any non-null reference value x, x.equals(x) should return true. It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. For any non-null reference value x, x.equals(null) should return false. 11 Quale eguaglianza rappresentare in equals? equals dovrebbe implementare uguaglianza di comportamento (behavioral equivalence): due oggetti sono equals se non è possibile distinguerli usando una sequenza di invocazioni di metodi della classe su uno dei due oggetti Motivo della scelta: altrimenti sorgono problemi con collezioni di oggetti mutabili che usano ad esempio equals per cercare un oggetto (si vedrà meglio con astrazioni polimorfe) Scelta poco seguita: in SDK ad esempio il metodo per la classe List è definito così: public boolean equals(object o) compares the specified object with this list... Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of iterator in the two lists are equal.... Questa definizione non è equivalente alla precedente!! Due liste sono equals a un certo punto, ma possono diventare!equals perche un elemento! 12 6

equals con oggetti immutabili Due oggetti immutabili sono equals sse hanno lo stesso stato astratto Motivo: due oggetti immutabili non possono essere distinti tramite mutazioni; inoltre gli observer della classe permettono solo di distinguere gli oggetti se hanno un diverso stato astratto (altrimenti le osservazioni non danno differenza) p e q non possono essere distinti tramite mutazioni: equals deve dare true quindi equals va ridefinito se la classe è immutabile (i reference sono diversi ma oggetti sono equals). Es. con String, equals controlla uguaglianza carattere per carattere a.equals(b) dà true NB: due oggetti (immutabili) concreti diversi con lo stesso stato astratto sono equals!! 13 Es. Implementazione equals Il tipo immutabile Point2D rappresenta punti in spazio 2D class Point2D { private int x; private int y; } public boolean equals (Point2D p) { return (x==p.x && y==p.y) } public boolean equals (Object z) { if (!(z instanceof Point2D)) return false; return equals((point2d ) z); } definisce un equals che restituisce true sse due punti hanno le stesse coordinate x e y overloading) utile per maggiore efficienza: se compilatore equals su Point2D, non si deve fare instanceof + casting. 14 7

il metodo equals e gli oggetti mutabili Due oggetti mutabili sono equals se e solo se sono lo stesso oggetto: List<Integer> s = new ArrayList<integer>(); List<Integer> t = new ArrayList<integer>(); if (s.equals s e t non sono equals anche se hanno lo stesso stato, perché sono distinguibili attraverso mutazioni: dopo s.insert(2), s e t hanno stati diversi! quindi equals non andrebbe ridefinito se la nuova classe è mutabile (es ArrayList) perché questa è proprio la definizione data in Object. Se serve eguaglianza più debole, definire un metodo ad hoc (come similar: oggetti indistinguibili usando solo observers, cioè stesso stato astratto) ad esempio, s.similar(t) deve dare true se s e t rappresentano liste uguali Questo principio è spesso ignorato in pratica (p.es. in tutte le librerie di Java), e può causare errori con i contenitori. Ad es., ArrayList ridefinisce equals anche se ArrayList è tipo mutabile. 17 Riassunto equals e clone Metodo Tipo Mutabile Tipo Immutabile equals Accettare definizione di Object (uguaglianza dei reference) (poco usato in pratica) Ridefinirlo come uguaglianza di stato astratto clone Ridefinirlo come copia dello stato astratto, se serve che sia disponibile Richiamare definizione di Object (copia del reference), se serve che sia disponibile 18 8