Slide complete Java

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();