Esercitazione su Java Ingegneria del Software - San Pietro Informazioni utili I Alessandro Rizzi I [email protected] Set di interi I Si definisca una classe che rappresenti un set di interi. I I I Collezione di oggetti Non ordinata Priva di ripetizioni Set di interi I Collezione di oggetti I I I Implementazione tramite array. Non ordinata Priva di ripetizioni I Si dovrà controllare ogni elemento prima dell’inserimento Set di interi I Attributi della classe: I I I elements - Array contenente gli interi (allocato ad una dimensione prefessata all’instanziazione della classe) size - Numero di elementi effettivamente presenti nell’array Metodi I I I Costruttori Appartenenza di un elemento Inserimento e rimozione di elementi Set di interi 1 class IntSet 2 { 3 private int elements[]; 4 private int currentSize; 5 public IntSet() {...} 6 public IntSet(int dim) {...} 7 public boolean contains(int n) {...} 8 public void add (int n) {...} 9 public void remove(int n) {...} 10 public String toString() {...} 11 } Numero complesso I Si progetti e implementi una classe per la gestione di un numero complesso (classe Complex). I Che funzionalità dovrà fornire? Numero complesso I Rappresentazione: I I Parte reale, parte immaginaria Operazioni: I I I I I Somma, differenza Uguaglianza (data la precisione richiesta) Modulo, fase Complesso coniugato Radici n-esime Numero complesso I Attributi: I I Metodi I I I I re, im (double); rappresentano la parte reale e la parte immaginaria. Costruttori: inizializzano l’oggetto. Osservatori: restituiscono informazioni sullo stato dell’oggetto. Produttori: restituiscono nuovo oggetti. La classe deve essere Immutabile I I Non deve essere possibili modificare lo stato dell’oggetto dopo la sua istanziazione. Nessun metodo può modificarne lo stato dopo l’istanziazione. Classe Complex 1 public class Complex { 2 private final double re, im; 3 public Complex() { ... } 4 public Complex(double re, double im) { ... } 5 public double re() { ... } 6 public static Complex fromPolarForm(double abs, double phase) { ... } 7 public double im() { ... } 8 public double abs() { ... } 9 public double phase() { ... } 10 public Complex conjugate() { ... } 11 public Complex sum(Complex other) { ... } 12 public Complex diff(Complex other) { ... } 13 public Complex mult(Complex other) { ... } 14 public boolean almostEquals(Complex other, double precision) { ... } 15 public ComplexSet getRoots(int degree) { ... } 16 } Set di numeri complessi I Si definisca una classe che rappresenti un set di numeri complessi. I I I Collezione di oggetti Non ordinata Priva di ripetizioni Set di numeri complessi I Attributi della classe: I I I I elements - Array contenente gli interi (allocato ad una dimensione prefessata all’instanziazione della classe) size - Numero di elementi effettivamente presenti nell’array precision - Precisione nel confronto tra numeri in virgola mobile Metodi I I I I Costruttori Appartenenza di un elemento Inserimento e rimozione di elementi Generazione dell’array contenente gli elementi dell’insieme Classe ComplexSet 1 class ComplexSet 2 { 3 private final Complex elements[]; 4 private int currentSize; 5 private final double precision; 6 private final static int MAX_SIZE = 100; 7 public ComplexSet() {...} 8 public ComplexSet(double p) {...} 9 public boolean contains(Complex n) {...} 10 public void add(Complex n) {...} 11 public void remove(Complex n) {...} 12 public Complex[] toArray() {...} 13 public int size() {...} 14 private int find(Complex n) {...} 15 } Morra cinese I Si implementi il gioco della morra cinese. I Giocatore umano contro computer. Persone e studenti I Si implementino le classi per rappresentare delle persone e degli studenti. I Si vuole tenere traccia del nome e della data di nascita di una persona. I Gli studenti sono delle persone cui è associata una lista di esami sostenuti. Classe Person 1 public class Person { 2 3 private String name; 4 5 private Calendar birthday; 6 7 Person(String name, Calendar birthday){ ... } 8 9 public String getName() { ... } 10 11 public Calendar getBirthday() { ... } 12 13 public String toString() { ... } 14 15 } Classe Grade 1 public class Grade { 2 private final String subject; 3 private final int points; 4 private final int credits; 5 6 public Grade(String subject, int points, int credits) { ... } 7 public String getSubject() { ... } 8 public int getPoints() { ... } 9 public int getCredits() { ... } 10 } Classe Student 1 public class Student extends Person { 2 3 private final List<Grade> grades; 4 5 public Student(String name, Calendar birthday) { ... } 6 7 public void addGrade(Grade grade) { ... } 8 9 public boolean canGraduate() { ... } 10 11 public double getWeightedGradeAverage() { ... } 12 13 private int totalCredits() { ... } 14 15 @Override 16 public String toString() { ... } 17 18 } Clone I clone() è un metodo (protected) definito in Object per restituire una copia dell’oggetto. I Per essere usato la classe deve implementare l’interfaccia Clonable, altrimenti l’implementazione di default non fa altro che lanciare una eccezione. I Può essere sostituito da un costruttore di copia. Collection in Java I L’attributo List<Grade> rappresenta una lista di voti. I Questo è un esempio dell’uso dei generics, classi parametriche rispetto ad altri tipi. I List è un’interfaccia implementata, ad esempio, dalla classe ArrayList. Forme geometriche I Si implementi una gerarchia di classe che rappresenti delle forme geometriche. I In particolare si implementi il calcolo dell’area, del perimetro e la rappresentazione su schermo. Classe Shape 1 public abstract class Shape { 2 3 public abstract double getArea(); 4 public abstract double getPerimeter(); 5 public abstract List<Point> getSequenceOfPointsToDraw(); 6 7 //Altro tipo di implementazione: 8 //Una classe fornisce primitive di disegno 9 public void draw(TwoDimensionalCanvas canvas) { 10 List<Point> points = getSequenceOfPointsToDraw(); 11 for (int i = 0; i < points.size() − 1; i++) { 12 canvas.drawLine(points.get(i), points.get(i + 1)); 13 } 14 } 15 } Classe Point 1 public class Point { 2 private final double x; 3 private final double y; 4 5 public Point(double x, double y) { ... } 6 7 public double getX() { ... } 8 9 public double getY() { ... } 10 11 public Point rotate(Point center, double degrees) { ... } 12 } Interfaccia TwoDimensionalCanvas 1 public interface TwoDimensionalCanvas { 2 3 void drawPoint(Point point); 4 5 void drawLine(Point firstEndPoint, Point secondEndPoint); 6 7 void drawCircle(Point center, double radius); 8 9 } Differenze tra gli approcci I Nella prima implementazione la figura deve esporre una rappresentazione compatibile con la classe esterna. Talvolta questo può essere problematico (vedasi cerchio). I Nella seconda implementazione è la figura a decidere come usare i metodi di disegno offerti. In tal modo le informazioni relative alla rappresentazione della figura restano interne ad essa (es. lista di punti). Ereditarietà e interfacce Animale Cane I Gatto Come è possibile estendere la gerarchia data aggiungendo animali che possano volare? Ereditarietà e interfacce Animale Cane Gatto Volatile Gufo I È possibile introdurre una classe volatile. I Come si modificherebbe aggiungendo gli animali che sanno nuotare? Ereditarietà e interfacce Animale Cane Gatto VolatileAcquatico Volatile Acquatico Gufo Pesce Anatra I Gerarchia complicata. I Non si vede che l’anatra è un animale acquatico. Soluzione? Animale Cane Gatto Volatile Gufo Pesce Acquatico Anatra I Ereditarietà multipla. I Tuttavia non supportata direttamente da Java (può generare problemi, e.g., diamond problem). I Realizzata tramite interfacce Implementazione 1 public class Anatra extends Animale implements Volatile, Acquatico { 2 // Deve implementare i metodi definiti in Volatile e in Acquatico 3 @Override 4 public void vola(){ ... } 5 @Override 6 public void nuota(){ ... } 7 } Classi vs Interfacce I Una classe rappresenta il fatto che un oggetto è qualcosa. I Una interfaccia rappresenta il fatto che la classe implementa un certo comportamento. Interfacce come tipi I Anche le interfacce possono essere usate come tipo di un riferimento. I Come tipo statico, un’interfaccia espone tutti i metodi che definisce. I L’implementazione utilizzata dipende dal tipo dinamico della classe (Binding dinamico). I Per gli assegnamenti dobbiamo considerare le relazioni di tipo/sotto-tipo. Quali operazioni sono consentite? 1 2 3 4 5 6 7 8 9 10 Animale g = new Gatto(); Pesce p = new Pesce(); Anatra a = new Anatra(); Volatile g1 = g; Volatile v = a; Nuotatore n = a; g.vola(); g.nuota(); v.vola(); n.nuota(); Quali operazioni sono consentite? 1 2 3 4 5 6 7 8 9 10 Animale g = new Gatto(); Pesce p = new Pesce(); Anatra a = new Anatra(); Volatile g1 = g; Volatile v = a; Nuotatore n = a; g.vola(); //No, g non vola g.nuota(); //No, g non nuota v.vola(); //OK n.nuota(); //OK Ancora forme geometriche I Si modifichi l’implementazione delle forme geometriche per permettere di “cambiare aspetto”. I Si definiscano opportunamente le interfacce Rotatable e Resizable. Interfacce Rotatable e Resizable 1 2 3 4 5 6 7 public interface Rotatable { Shape rotate(double angle); } public interface Resizable { Shape resize(double scale); } I Una forma modificata è ancora una forma. I Il tipo di ritorno è un generico Shape. Classe Square 1 public class Square extends Shape implements Resizable, Rotatable{ 2 //... 3 4 @Override 5 public Square rotate(double angle) { 6 return new Square(initialPoint, orientation+angle, sideLength); 7 } 8 9 @Override 10 public Square resize(double scale) { 11 return new Square(initialPoint, orientation, sideLength∗scale); 12 } 13 14 } I Si ha covarianza sul tipo di ritorno: è un sottotipo di Shape. Classe Circle 1 public class Circle extends Shape implements Resizable { 2 //... 3 4 @Override 5 public Circle resize(double scale) { 6 return new Circle(center, radius∗scale); 7 } 8 9 } Generics I È possibile definire tipi parametrici tramite l’uso di tipi generici. I Una classe generica è una classe che dipende da un tipo non specificato (nell’ esempio E). 1 public class GenericTest<E>{ 2 private E var; 3 public GenericTest(E var){ 4 this.var=var; 5 } 6 public E getVar() { 7 return var; 8 } 9 public void setVar(E var) { 10 this.var=var; 11 } 12 } Generics I I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Alla definizione di una variabile di una classe generica è necessario specificare il tipo corrente che sostituirà il tipo parametrico indicato. È possibile utilizzare un qualunque tipo di riferimento (no tipi primitivi). public class GenericTest<E>{ private E var; public GenericTest(E var){ this.var=var; } public E getVar() { return var; } public void setVar(E var) { this.var=var; } } GenericTest<Integer> intero = new GenericTest<Integer>(10); GenericTest<String> stringa = new GenericTest<String>("Ciao mondo!"); Generics I È possibile vincolare il tipo generico ad essere un sottotipo di un tipo dato (covarianza). I Il metodo mostrato può gestire una qualsiasi collezione i cui elementi estendono la classe SuperClass. 1 public void method(Collection<? extends SuperClass> collection); I È anche possibile vincolare il tipo generico ad essere un tipo ereditato da un tipo dato (controvarianza). I Il metodo mostrato può gestire una qualsiasi collezione i cui elementi sono sottotipi della classe SubClass. 1 public void method(Collection<? super SubClass> collection); Java Collections Framework Map Collection Set SortedSet I List Queue SortedMap Deque Costituiscono una struttura dedicata alla gestione di gruppi di oggetti. Operazioni basilari 1 2 3 4 5 6 7 8 9 10 11 12 int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element);// Opzionale boolean remove(Object element);// Opzionale Iterator iterator(); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c);// Opzionale boolean removeAll(Collection<?> c);// Opzionale boolean retainAll(Collection<?> c);// Opzionale void clear();// Opzionale Set I Un Set rappresenta un insieme di oggetti privo di elementi duplicati. I In generale non conserva un ordinamento, tranne nel caso dell’interfaccia SortedSet. Alcune implementazioni sono: I I I I HashSet TreeSet LinkedHashSet List I I Una List rappresenta un sequenza di oggetti che può contenere duplicati. Alcune implementazioni sono: I I I ArrayList LinkedList Vector Operazioni basilari 1 2 3 4 5 6 7 8 9 10 11 12 E get(int index); E set(int index, E element); boolean add(E element); void add(int index, E element); E remove(int index); boolean addAll(int index, Collection<?extendsE> c); int indexOf(Object o); int lastIndexOf(Object o); ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); Queue I I Una Queue rappresenta una coda di oggetti che può contenere duplicati. Una implementazione è: I I LinkedList Il sottotipo Deque rappresenta una coda con entrambi gli estremi manipolabili (double ended queue). Operazione insert remove examine Lancia eccezione add(e) remove() element() Valore speciale offer(e) poll() peek() Map I Una Map rappresenta una associazione di valori a delle chiavi. I Non ammette duplicati, ma ammette valori nulli. Alcune implementazioni sono: I I I I HashMap TreeMap LinkedHashMap Operazioni basilari 1 2 3 4 5 6 7 8 9 10 11 V put(K key, V value); V get(Object key); V remove(Object key); boolean containsKey(Object key); boolean containsValue(Object value); int size(); boolean isEmpty(); Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K,V>> entrySet(); Hashtable I Una Hashtable è un’implementazione di una Map. I Non ammette valori nulli. I È sincronizzata. 1 Hashtable<String, Integer> numbers 2 = new Hashtable<String, Integer>(); 3 numbers.put("one", 1); 4 numbers.put("two", 2); 5 numbers.put("three", 3); Interfaccia Iterator<E> I L’interfaccia Iterator<E> permette di scandire e rimuovere oggetti da collezioni. I È composta dai metodi: 1 boolean hasNext() 2 E next(); 3 void remove(); I Esempio 1 Iterator<String> iterator = list.iterator(); 2 while(iteratore.hasNext()){ 3 string = iterator.next();//Elemento successivo 4 iterator.remove();//Rimuovi elemento corrente 5 } Interfaccia Iterable<T> I L’interfaccia Iterable<T> permette di implementare il for generalizzato. I È composta dal metodo: 1 Iterator<T> iterator(); I È possibile usare il for generalizzato su oggetti che implementano tale interfaccia. HashCode I hashCode() è un metodo definito in Object. I L’intero restituito dipende dallo stato dell’oggetto, in particolare instanze uguali ritornano hash uguali. I Deve essere ridefinito nel caso si ridefinisca il metodo equals(). Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package a; ...... class First { ...... int x; ...... int y; ...... void h() { y = −1; } } ...... class Second extends First { ...... void f(int x) { this.x = x; h(); } } 1 package b; 2 import a.∗; 3 4 class Third { 5 public static void main(String[] s) { 6 Second z = new Second(); 7 z.f(3); 8 } 9 10 class Fourth extends First { 11 void g() { 12 h(); 13 } 14 } Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package a; public class First { int x; private int y; protected void h() { y = −1; } } public class Second extends First { public void f(int x) { this.x = x; h(); } } 1 package b; 2 import a.∗; 3 4 class Third { 5 public static void main(String[] s) { 6 Second z = new Second(); 7 z.f(3); 8 } 9 10 class Fourth extends First { 11 void g() { 12 h(); 13 } 14 } Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 1 2 1 2 3 //Primo file 4 package A; 5 6 public class C1 { 7 8 public void m1() { } 9 protected void m2 () { } 10 private void m3 () { } 11 12 } 13 14 C2 x = new C2(); //Dire se corretta e 15 16 x.m1(); //che output produrrebbe 17 18 19 //Secondo file package B; import A.∗; public class C2 extends C1 { public void m1() { System.out.print("Salve"); m2(); m3(); } protected void m2 () { System.out.print(", mondo"); } private void m3() { System.out.print("!"); } Modificatori di visibilità I La definizione di C2 è corretta. I Il metodo m1 può utilizzare i metodi m2 e m3. I L’output è “Salve, mondo!”. Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 1 2 1 2 //Primo file 3 package A; 4 5 public class C1 { 6 7 public void m1() { } 8 protected void m2 () { } 9 private void m3 () { } 10 11 } 12 13 C2 x = new C2(); //Dire se corretta e 14 15 x.m1(); //che output produrrebbe 16 17 package B; import A.∗; public class C2 extends C1 { public void m1() { System.out.print("Salve"); m2(); m3(); } protected void m2() { System.out.print(", mondo"); } //Nessuna definizione di m3 } Modificatori di visibilità I In questo caso C2 non ha la visibilità di m3. I Errore di compilazione! Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 1 2 1 2 3 //Primo file 4 package A; 5 6 public class C1 { 7 8 public void m1() { } 9 protected void m2 () { } 10 private void m3 () { } 11 12 } 13 14 C2 x = new C2(); //Dire se corretta e 15 x.m1(); //che output produrrebbe 16 17 18 package B; import A.∗; public class C2 extends C1 { public void m1() { System.out.print("Salve"); m2(); m3(); } //Nessuna definizione di m2 private void m3() { System.out.print("!"); } } Modificatori di visibilità I In questo caso C2 ha la visibilità di m2 definito in C1. I L’output è “Salve!”. Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import A.∗; import B.∗; public class C3 { public static void main(String[] s){ C1 c1; C2 c2; Object o; c1 = new C1(); c1.m1(); c2 = new C2(); c2.m2(); c1 = c2; c1.m1(); c2 = new C1(); o = new C1(); c2 = (C2)o; o = new C2(); c1 = (C1) o; c1.m1(); } } I Indicare gli errori a compile-time ed eliminare le istruzioni che li generano I Dire se ci sono errori a run-time ed eliminare le istruzioni che li generano I Determinare l’output del programma Modificatori di visibilità 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import A.∗; import B.∗; public class C3 { public static void main(String[] s){ C1 c1; C2 c2; Object o; c1 = new C1(); c1.m1(); c2 = new C2(); c2.m2(); //m2 protected c1 = c2; c1.m1(); c2 = new C1(); //C1 superclasse di C2 o = new C1(); c2 = (C2)o; //Errore a run−time: o istanza di C1 o = new C2(); c1 = (C1) o; c1.m1(); } } Tipi 1 class Persona{ 2 String saluto(){ 3 return "Buongiorno"; 4 }} 5 class PersonaEducata extends Persona { 6 String saluto() { 7 return "Buongiorno a lei"; 8 }} 9 class PersonaMaleducata extends Persona { 10 String saluto() { 11 return "Faccia silenzio!"; 12 }} 13 class PersonaMaleducatissima extends PersonaMaleducata { 14 String saluto() { 15 return "Non mi rompa!"; 16 }} 1 Persona p = new Persona(); 2 PersonaEducata pe =new PersonaEducata(); 3 PersonaMaleducata pm =new PersonaMaleducata(); 4 PersonaMaleducatissima pmm=new PersonaMaleducatissima(); 5 p.saluto(); 6 pe = p; 7 p = pe; 8 p.saluto(); 9 pe = pm; 10 pe.saluto(); 11 pm.saluto(); 12 p = new PersonaMaleducata(); 13 p.saluto(); 14 pm = p; 15 pmm = (PersonaMaleducatissima) 16 pm; 17 pmm.saluto();
© Copyright 2024 Paperzz