• Non ci sono risultati.

Interfacce e Polimorfismo Interfacce e Polimorfismo

N/A
N/A
Protected

Academic year: 2021

Condividi "Interfacce e Polimorfismo Interfacce e Polimorfismo"

Copied!
63
0
0

Testo completo

(1)

Interfacce e Polimorfismo Interfacce e Polimorfismo

C. Horstmann

C. Horstmann

Fondamenti di programmazione e Java 2

Fondamenti di programmazione e Java 2

3^ edizione Apogeo

3^ edizione Apogeo

trad. Nicola Fanizzi

trad. Nicola Fanizzi

corso di Programmazione, CdS: Informatica TPS

corso di Programmazione, CdS: Informatica TPS

Dip. di Informatica, Università degli studi di Bari

Dip. di Informatica, Università degli studi di Bari

(2)

2 2

Obiettivi Obiettivi

 Imparare ad usare le interfacce Imparare ad usare le interfacce

 Essere in grado di fare conversioni tra riferimenti a Essere in grado di fare conversioni tra riferimenti a classi e ad interfacce

classi e ad interfacce

 Capire il concetto di polimorfismo Capire il concetto di polimorfismo

 Imparare ad usare le interfacce per il dis- Imparare ad usare le interfacce per il dis- accoppiamento delle classi

accoppiamento delle classi

(3)

3 3

Obiettivi Obiettivi

 Imparare ad implementare classi helper come classi Imparare ad implementare classi helper come classi interne

interne

 Accedere a variabili del contesto superiore Accedere a variabili del contesto superiore

 Implementare eventi ascoltatori (listener) per eventi Implementare eventi ascoltatori (listener) per eventi temporizzatori (timer)

temporizzatori (timer)

(4)

4 4

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

 Usare tipi Interfaccia per rendere il codice più Usare tipi Interfaccia per rendere il codice più riusabile

riusabile

 Nel Cap. 7 (sulle Iterazioni), abbiamo creato un Nel Cap. 7 (sulle Iterazioni), abbiamo creato un DataSet

DataSet per trovare la media e il massimo di un per trovare la media e il massimo di un insieme di valori (numeri)

insieme di valori (numeri)

 Che fare se volessimo trovare media e massimo di Che fare se volessimo trovare media e massimo di un insieme di valori di tipo

un insieme di valori di tipo BankAccount BankAccount ? ?

(5)

5 5

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

public class

public class DataSetDataSet // Modificato per oggetti BankAccount// Modificato per oggetti BankAccount {{

. . . . . .

public void

public void addadd(BankAccount x)(BankAccount x) {

{

sum = sum + x.getBalance();

sum = sum + x.getBalance();

if (count == 0 || maximum.getBalance() < x.getBalance()) if (count == 0 || maximum.getBalance() < x.getBalance()) maximum = x;

maximum = x;

count++;

count++;

} }

public BankAccount

public BankAccount getMaximumgetMaximum() () {

{

return maximum;

return maximum;

} }

private double

private double sumsum; ; private BankAccount

private BankAccount maximummaximum; ; private int

private int countcount; ; } }

(6)

6 6

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

 Oppure si supponga di voler trovare la moneta con il Oppure si supponga di voler trovare la moneta con il valore più alto in un insieme di monete

valore più alto in un insieme di monete

Si dovrebbe di nuovo modificare la classe Si dovrebbe di nuovo modificare la classe DataSet

DataSet (come segue...) (come segue...)

(7)

7 7

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

public class

public class DataSetDataSet // Modificata per oggetti Coin// Modificata per oggetti Coin { {

. . . . . .

public void

public void addadd(Coin x) (Coin x) {

{

sum = sum + x.getValue();

sum = sum + x.getValue();

if (count == 0 || maximum.getValue() < x.getValue()) if (count == 0 || maximum.getValue() < x.getValue()) maximum = x;

maximum = x;

count++;

count++;

} }

public Coin

public Coin getMaximumgetMaximum() () {

{

return maximum;

return maximum;

} }

private double

private double sumsum; ; private Coin

private Coin maximummaximum; ; private int

private int countcount; ; } }

(8)

8 8

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

 Il funzionamento dell'analisi dei dati è lo stesso in Il funzionamento dell'analisi dei dati è lo stesso in tutti i casi; cambiano i dettagli sulla misura

tutti i casi; cambiano i dettagli sulla misura

 Le classi potrebbero accordarsi su un metodo Le classi potrebbero accordarsi su un metodo getMeasure

getMeasure che dà la misura da usare per che dà la misura da usare per l'analisi

l'analisi

 Si può implementare una sola classe riusabile Si può implementare una sola classe riusabile DataSet

DataSet il cui metodo il cui metodo add add sia del tipo: sia del tipo:

sum = sum +

sum = sum + xx.getMeasure(); .getMeasure();

if (count == 0 || maximum.getMeasure() <

if (count == 0 || maximum.getMeasure() < xx.getMeasure()) .getMeasure()) maximum =

maximum = xx; ; count++;

count++;

(9)

9 9

Usare le Interfacce Usare le Interfacce per il Riuso del Codice per il Riuso del Codice

 Qual è il tipo della variabile Qual è il tipo della variabile x x ? ?

x x dovrebbe riferirsi ad una qualsiasi classe che ha il dovrebbe riferirsi ad una qualsiasi classe che ha il metodo

metodo getMeasure getMeasure

 In Java, si usa un tipo interfaccia In Java, si usa un tipo interfaccia type per specificare type per specificare operazioni richieste

operazioni richieste

 La dichiarazione di una interfaccia elenca i metodi La dichiarazione di una interfaccia elenca i metodi (con le loro firme) richieste dal tipo di interfaccia (con le loro firme) richieste dal tipo di interfaccia

public interface Measurable public interface Measurable { {

double getMeasure();

double getMeasure();

}}

(10)

10 10

Confronto Classi - Interfacce Confronto Classi - Interfacce

 Un tipo interfaccia è simile ad un tipo di classe Un tipo interfaccia è simile ad un tipo di classe ma vi sono delle importanti differenze:

ma vi sono delle importanti differenze:

Tutti i metodi di un tipo interfaccia sono Tutti i metodi di un tipo interfaccia sono astratti astratti ossia essi ossia essi non hanno una (implementazione nell'interfaccia)

non hanno una (implementazione nell'interfaccia)

Tutti i metodi di un tipo interfaccia sono automaticamente Tutti i metodi di un tipo interfaccia sono automaticamente pubblici

pubblici

Un tipo interfaccia Un tipo interfaccia non non ha campi istanza ha campi istanza

(11)

11 11

Dataset

Dataset Generica Generica per Oggetti

per Oggetti Measurable Measurable

public class DataSet public class DataSet { {

. . . . . .

public void add(Measurable x) public void add(Measurable x) {

{

sum = sum + x.getMeasure();

sum = sum + x.getMeasure();

if (count == 0 || maximum.getMeasure() < x.getMeasure()) if (count == 0 || maximum.getMeasure() < x.getMeasure()) maximum = x;

maximum = x;

count++;

count++;

} }

public Measurable getMaximum() public Measurable getMaximum() {

{

return maximum;

return maximum;

} }

private double sum;

private double sum;

private Measurable maximum;

private Measurable maximum;

private int count;

private int count;

}}

(12)

12 12

Implementazione Implementazione di un Tipo Interfaccia di un Tipo Interfaccia

 Si usa la parola chiave Si usa la parola chiave implements implements per indicare per indicare che una classe implementa un tipo di Interfaccia

che una classe implementa un tipo di Interfaccia

 Una classe può implementare Una classe può implementare più di una più di una interfaccia interfaccia

La classe La classe deve deve definire tutti i metodi richiesti da tutte le definire tutti i metodi richiesti da tutte le interfacce che implementa

interfacce che implementa

public class BankAccount implements Measurable public class BankAccount implements Measurable { {

public double getMeasure() public double getMeasure() {

{

return balance;

return balance;

} }

// metodi e campi addizionali // metodi e campi addizionali } }

(13)

13 13

Implementazione Implementazione di un Tipo Interfaccia di un Tipo Interfaccia

 Altro esempio: Altro esempio:

public class Coin implements Measurable public class Coin implements Measurable { {

public double getMeasure() public double getMeasure() {

{

return value;

return value;

} }

. . . . . . }}

(14)

14 14

Diagrammi UML di

Diagrammi UML di Dataset Dataset e Classi Correlate e Classi Correlate

 Le interfacce possono ridurre l'accoppiamento tra Le interfacce possono ridurre l'accoppiamento tra classi

classi

Si noti che DataSet Si noti che DataSet è disaccoppiata da è disaccoppiata da BankAccount

BankAccount e da e da Coin Coin

 Notazione UML: Notazione UML:

Le interfacce sono etichettate con un indicatore stereotipo Le interfacce sono etichettate con un indicatore stereotipo

«interface»

«interface»

Un arco punteggiato terminante con freccia triangolare Un arco punteggiato terminante con freccia triangolare denota una relazione "

denota una relazione " is-a is-a " ( " ( è-un/una è-un/una ) tra una classe ed ) tra una classe ed un'interfaccia

un'interfaccia

Una linea tratteggiata terminante con freccia triangolare a Una linea tratteggiata terminante con freccia triangolare a V denota una relazione

V denota una relazione di uso di uso o o di dipendenza di dipendenza

(15)

15 15

Diagrammi UML di

Diagrammi UML di Dataset Dataset e Classi Correlate e Classi Correlate

Figure 2:

UML Diagram of Dataset Class and the Classes that Implement the Measurable Interface

(16)

16 16

Sintassi 11.1:

Sintassi 11.1:

Definire un Interfaccia Definire un Interfaccia

    public public interface interface InterfaceName InterfaceName { {

// firme dei metodi // firme dei metodi } }

Esempio Esempio : :

    public interface Measurable public interface Measurable { {

double getMeasure();

double getMeasure();

} }

Scopo Scopo : definire una interfaccia e le firme dei suoi : definire una interfaccia e le firme dei suoi metodi che sono automaticamente pubblici

metodi che sono automaticamente pubblici

(17)

17 17

Sintassi 11.2:

Sintassi 11.2:

Implementare un'Interfaccia Implementare un'Interfaccia

public class

public class ClassName ClassName implementsimplements InterfaceName, InterfaceName, InterfaceName, InterfaceName, ...

...

{{

// metodi // metodi

// variabili d'istanza// variabili d'istanza }}

Esempio Esempio : :

public class BankAccount implements Measurable public class BankAccount implements Measurable { {

// Other BankAccount methods // Other BankAccount methods public double getMeasure() public double getMeasure() { {

// Method implementation // Method implementation } }

}}

Scopo

Scopo : definire una nuova classe che implementa i metodi di una interfaccia : definire una nuova classe che implementa i metodi di una interfaccia

(18)

18 18

DataSetTester.java DataSetTester.java

01: /**01: /**

02:

02: Programma di collaudo per la classe DataSet.Programma di collaudo per la classe DataSet.

03: */03: */

04: public class DataSetTester 04: public class DataSetTester 05: {

05: {

06: public static void main(String[] args) 06: public static void main(String[] args) 07: {

07: {

08: DataSet bankData = new DataSet();

08: DataSet bankData = new DataSet();

09: 09:

10: bankData.add(new BankAccount(0));

10: bankData.add(new BankAccount(0));

11: bankData.add(new BankAccount(10000));

11: bankData.add(new BankAccount(10000));

12: bankData.add(new BankAccount(2000));

12: bankData.add(new BankAccount(2000));

13: 13:

14: System.out.println("Average balance = "

14: System.out.println("Average balance = "

15: + bankData.getAverage());

15: + bankData.getAverage());

16: Measurable max = bankData.getMaximum();

16: Measurable max = bankData.getMaximum();

17: System.out.println("Highest balance = "

17: System.out.println("Highest balance = "

18: + max.getMeasure());

18: + max.getMeasure());

(19)

19 19

DataSetTester.java DataSetTester.java

19: 19:

20: DataSet coinData = new DataSet();

20: DataSet coinData = new DataSet();

21: 21:

22: coinData.add(new Coin(0.25, "quarter"));

22: coinData.add(new Coin(0.25, "quarter"));

23: coinData.add(new Coin(0.1, "dime"));

23: coinData.add(new Coin(0.1, "dime"));

24: coinData.add(new Coin(0.05, "nickel"));

24: coinData.add(new Coin(0.05, "nickel"));

25: 25:

26: System.out.println("Average coin value = "

26: System.out.println("Average coin value = "

27: + coinData.getAverage());

27: + coinData.getAverage());

28: max = coinData.getMaximum();

28: max = coinData.getMaximum();

29: System.out.println("Highest coin value = "

29: System.out.println("Highest coin value = "

30: + max.getMeasure());

30: + max.getMeasure());

31: } 31: } 32: } 32: }

(20)

20 20

DataSetTester.java DataSetTester.java

Average balance = 4000.0 Average balance = 4000.0 Highest balance = 10000.0 Highest balance = 10000.0

Average coin value = 0.13333333333333333 Average coin value = 0.13333333333333333 Highest coin value = 0.25

Highest coin value = 0.25

 Output: Output:

(21)

21 21

Conversioni tra Conversioni tra Tipi di Classe e di Interfaccia Tipi di Classe e di Interfaccia

 Si può fare una conversione da un tipo di classe ad Si può fare una conversione da un tipo di classe ad uno di interfaccia, ammesso che la classi implementi uno di interfaccia, ammesso che la classi implementi

l'interfaccia l'interfaccia

BankAccount account = new BankAccount(10000);

BankAccount account = new BankAccount(10000);

Measurable x = account;

Measurable x = account; // va bene// va bene

Coin dime = new Coin(0.1, "dime");

Coin dime = new Coin(0.1, "dime");

Measurable x = dime;

Measurable x = dime; // va bene ugualmente// va bene ugualmente

(22)

22 22

Conversioni tra Conversioni tra Tipi di Classe e di Interfaccia Tipi di Classe e di Interfaccia

 Non si posso fare conversioni tra tipi non correlati Non si posso fare conversioni tra tipi non correlati

perché perché

Rectangle

Rectangle non implementa non implementa Measurable Measurable

Measurable x = new Rectangle(5, 10, 20, 30);

Measurable x = new Rectangle(5, 10, 20, 30); // ERRORE// ERRORE

(23)

23 23

Cast Cast

 Aggiungere oggetti Aggiungere oggetti Coin Coin ad uno di tipo ad uno di tipo DataSet DataSet

 Cosa se ne può fare? Non è di tipo Cosa se ne può fare? Non è di tipo Coin Coin

DataSet coinData = new DataSet();

DataSet coinData = new DataSet();

coinData.add(new Coin(0.25, "quarter"));

coinData.add(new Coin(0.25, "quarter"));

coinData.add(new Coin(0.1, "dime"));

coinData.add(new Coin(0.1, "dime"));

. . . . . .

Measurable max = coinData.getMaximum();

Measurable max = coinData.getMaximum();

// ottiene la moneta più grande // ottiene la moneta più grande

String name = max.getName();

String name = max.getName(); // ERRORE// ERRORE

(24)

24 24

Cast Cast

 Serve un cast per convertire da un tipo interfaccia ad Serve un cast per convertire da un tipo interfaccia ad un tipo di classe

un tipo di classe

 è un oggetto è un oggetto Coin Coin ma il compilatore non lo sa ma il compilatore non lo sa Si applica allora il cast:

Si applica allora il cast:

 E si sbaglia e max non è un E si sbaglia e max non è un Coin Coin allora il allora il compilatore lancia un'eccezione

compilatore lancia un'eccezione

Coin maxCoin = (Coin) max;

Coin maxCoin = (Coin) max;

String name = maxCoin.getName();

String name = maxCoin.getName();

(25)

25 25

Cast Cast

 Differenze con il cast sui numeri: Differenze con il cast sui numeri:

cast sui numeri: cast sui numeri:

si deve essere consapevoli della perdita di informazione si deve essere consapevoli della perdita di informazione

cast su tipi di oggetti: si deve essere consapevoli del cast su tipi di oggetti: si deve essere consapevoli del rischio di causare eccezioni

rischio di causare eccezioni

(26)

26 26

Polimorfismo Polimorfismo

 Una variabile interfaccia mantiene il riferimento ad un Una variabile interfaccia mantiene il riferimento ad un oggetto della classe che implementa l'interfaccia

oggetto della classe che implementa l'interfaccia Measurable x;

Measurable x;

Si noti che l'oggetto al quale

Si noti che l'oggetto al quale x x si riferisce non il tipo si riferisce non il tipo Measurable

Measurable

Il tipo dell'oggetto è una delle classi che implementano Il tipo dell'oggetto è una delle classi che implementano l'interfaccia

l'interfaccia Measurable Measurable

x = new BankAccount(10000);

x = new BankAccount(10000);

x = new Coin(0.1, "dime");

x = new Coin(0.1, "dime");

(27)

27 27

Polimorfismo Polimorfismo

 Si può chiamare qualunque metodo dell'interfaccia: Si può chiamare qualunque metodo dell'interfaccia:

 Quale metodo viene chiamato ? Quale metodo viene chiamato ?

double m = x.getMeasure();

double m = x.getMeasure();

(28)

28 28

Polimorfismo Polimorfismo

 Dipende dall'oggetto reale Dipende dall'oggetto reale

 Se Se x x si riferisce ad un conto bancario, si chiama si riferisce ad un conto bancario, si chiama BankAccount.getMeasure

BankAccount.getMeasure

 Se Se x x si riferisce ad una moneta, si chiama si riferisce ad una moneta, si chiama Coin.getMeasure

Coin.getMeasure

Polimorfismo Polimorfismo ( ( molte forme molte forme ): ):

comportamento che varia a seconda del reale tipo di comportamento che varia a seconda del reale tipo di

un oggetto

un oggetto

(29)

29 29

Polimorfismo Polimorfismo

 Chiamato anche Chiamato anche late binding late binding : :

risolto al momento dell'esecuzione (a runtime) risolto al momento dell'esecuzione (a runtime)

 Diverso dal Diverso dal sovraccarico sovraccarico (overloading): (overloading):

che viene risolto dal compilatore (

che viene risolto dal compilatore ( early binding early binding ) )

(30)

30 30

Usare Interfacce per i Callback Usare Interfacce per i Callback

 Limiti dell'interfaccia Limiti dell'interfaccia Measurable Measurable : :

Si può aggiungere l'interfaccia Si può aggiungere l'interfaccia Measurable Measurable solo a solo a classi sotto i proprio controllo

classi sotto i proprio controllo

Si può misurare un oggetto solo in una sola maniera Si può misurare un oggetto solo in una sola maniera

Es., non si può analizzare un insieme di risparmi in base Es., non si può analizzare un insieme di risparmi in base

al saldo ed anche al tasso d'interesse al saldo ed anche al tasso d'interesse

 Meccanismo del Meccanismo del Callback Callback : consente ad una classe : consente ad una classe di richiamare (

di richiamare ( call back call back ) un metodo specifico quando ) un metodo specifico quando si ha bisogno di maggiore informazione

si ha bisogno di maggiore informazione

(31)

31 31

Usare Interfacce per i Callback Usare Interfacce per i Callback

 Nella precedente implementazione di Nella precedente implementazione di DataSet DataSet la la responsabilità della misura ricade sugli oggetti stessi responsabilità della misura ricade sugli oggetti stessi

aggiunti aggiunti

 Alternativa: passare ad un metodo l'oggetto da Alternativa: passare ad un metodo l'oggetto da misurare

misurare

 Object Object è il “ è il “ minimo comune denominatore” minimo comune denominatore” di di tutte le classi

tutte le classi

public interface Measurer public interface Measurer { {

double measure(Object anObject);

double measure(Object anObject);

} }

(32)

32 32

Usare Interfacce per i Callback Usare Interfacce per i Callback

 Il metodo Il metodo add add chiede al misuratore ( chiede al misuratore ( measurer measurer ) ) e non all'oggetto aggiunto di operare la misura

e non all'oggetto aggiunto di operare la misura

public void add(Object x) public void add(Object x) { {

sum = sum + measurer.measure(x);

sum = sum + measurer.measure(x);

if (count == 0 ||

if (count == 0 ||

measurer.measure(maximum) < measurer.measure(x))measurer.measure(maximum) < measurer.measure(x)) maximum = x;

maximum = x;

count++;

count++;

} }

(33)

33 33

Usare Interfacce per i Callback Usare Interfacce per i Callback

 Si possono definire classi Si possono definire classi Measurer Measurer specifiche specifiche per poter fare ogni tipo di misura

per poter fare ogni tipo di misura

public class RectangleMeasurer implements Measurer public class RectangleMeasurer implements Measurer { {

public double measure(Object anObject) public double measure(Object anObject) {

{

Rectangle aRectangle = (Rectangle) anObject;

Rectangle aRectangle = (Rectangle) anObject;

double area = double area =

aRectangle.getWidth() * aRectangle.getHeight();

aRectangle.getWidth() * aRectangle.getHeight();

return area;

return area;

} } }}

(34)

34 34

Usare Interfacce per i Callback Usare Interfacce per i Callback

 Si deve fare il cast da Si deve fare il cast da Object Object a a Rectangle Rectangle

 Si passa l'oggetto Si passa l'oggetto Measurer Measurer al costruttore di al costruttore di DataSet

DataSet : :

Rectangle aRectangle = (Rectangle) anObject;

Rectangle aRectangle = (Rectangle) anObject;

Measurer m = new RectangleMeasurer();

Measurer m = new RectangleMeasurer();

DataSet data = new DataSet(m);

DataSet data = new DataSet(m);

data.add(new Rectangle(5, 10, 20, 30));

data.add(new Rectangle(5, 10, 20, 30));

data.add(new Rectangle(10, 20, 30, 40));

data.add(new Rectangle(10, 20, 30, 40));

. . . . . .

(35)

35 35

Diagramma UML dell'Interfaccia Diagramma UML dell'Interfaccia

Measurer

Measurer e Classi Correlate e Classi Correlate

 Si noti che la classe Si noti che la classe Rectangle Rectangle è disaccoppiata è disaccoppiata dall'interfaccia

dall'interfaccia Measurer Measurer

Figure 2:

UML Diagram of the DataSet Class and the Measurer Interface

(36)

36 36

DataSet.java DataSet.java

01: /**

01: /**

02: Calcola la media di un insieme di valori.

02: Calcola la media di un insieme di valori.

03: */

03: */

04: public class DataSet 04: public class DataSet 05: {

05: { 06:

06: /**/**

07: Costruisce un dataset vuoto con un dato measurer.

07: Costruisce un dataset vuoto con un dato measurer.

08: @param aMeasurer il measurer che è usato per 08: @param aMeasurer il measurer che è usato per

// misurare i valori // misurare i valori 09: */

09: */

10: public DataSet(Measurer aMeasurer) 10: public DataSet(Measurer aMeasurer) 11: {

11: {

12: sum = 0;

12: sum = 0;

13: count = 0;

13: count = 0;

14: maximum = null;

14: maximum = null;

15: measurer = aMeasurer;

15: measurer = aMeasurer;

16: } 16: } 17: 17:

(37)

37 37

DataSet.java DataSet.java

18: /**

18: /**

19: aggiunge un valore al dataset.

19: aggiunge un valore al dataset.

20: @param x un valore 20: @param x un valore 21: */

21: */

22: public void add(Object x) 22: public void add(Object x) 23: {

23: {

24: sum = sum + measurer.measure(x);

24: sum = sum + measurer.measure(x);

25: if (count == 0 25: if (count == 0

26: || measurer.measure(maximum) 26: || measurer.measure(maximum)

< measurer.measure(x))< measurer.measure(x)) 27: maximum = x;

27: maximum = x;

28: count++;

28: count++;

29: } 29: } 30: 30:

31: /**

31: /**

32: ottiene la media dei valori aggiunti.

32: ottiene la media dei valori aggiunti.

33: @return la media o 0 se nessun dato è stato aggiunto 33: @return la media o 0 se nessun dato è stato aggiunto 34: */

34: */

(38)

38 38

DataSet.java DataSet.java

35: public double getAverage() 35: public double getAverage() 36: {

36: {

37: if (count == 0) return 0;

37: if (count == 0) return 0;

38: else return sum / count;

38: else return sum / count;

39: } 39: } 40: 40:

41:

41: /**/**

42:

42: Calcolo l dato più grande.Calcolo l dato più grande.

43:

43: @return massimo o 0 se nessun dato è stato aggiunto@return massimo o 0 se nessun dato è stato aggiunto 44:

44: */*/

45: public Object getMaximum() 45: public Object getMaximum() 46: {

46: {

47: return maximum;

47: return maximum;

48: } 48: } 49: 49:

(39)

39 39

DataSet.java DataSet.java

50: private double sum;

50: private double sum;

51: private Object maximum;

51: private Object maximum;

52: private int count;

52: private int count;

53: private Measurer measurer;

53: private Measurer measurer;

54: } 54: }

(40)

40 40

DataSetTester2.java DataSetTester2.java

01: import java.awt.Rectangle;

01: import java.awt.Rectangle;

02: 02:

03: /**

03: /**

04: Dimostratore dell'uso di un Measurer.

04: Dimostratore dell'uso di un Measurer.

05: */

05: */

06: public class DataSetTester2 06: public class DataSetTester2 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: Measurer m = new RectangleMeasurer();

10: Measurer m = new RectangleMeasurer();

11: 11:

12: DataSet data = new DataSet(m);

12: DataSet data = new DataSet(m);

13: 13:

14: data.add(new Rectangle(5, 10, 20, 30));

14: data.add(new Rectangle(5, 10, 20, 30));

15: data.add(new Rectangle(10, 20, 30, 40));

15: data.add(new Rectangle(10, 20, 30, 40));

16: data.add(new Rectangle(20, 30, 5, 10));

16: data.add(new Rectangle(20, 30, 5, 10));

17: 17:

18: System.out.println("Average area = " + 18: System.out.println("Average area = " + data.getAverage());

data.getAverage());

19: Rectangle max = (Rectangle) data.getMaximum();

19: Rectangle max = (Rectangle) data.getMaximum();

20: System.out.println("Maximum area rectangle = " +max);

20: System.out.println("Maximum area rectangle = " +max);

21: } 21: }

(41)

41 41

Measurer.java Measurer.java

01: /**

01: /**

02: Descrive ogni classe i cui oggetti possono misurare 02: Descrive ogni classe i cui oggetti possono misurare altri oggetti.

altri oggetti.

03: */

03: */

04: public interface Measurer 04: public interface Measurer 05: {

05: {

06: /**

06: /**

07: Calcola la misura di un oggeto.

07: Calcola la misura di un oggeto.

08: @param anObject l'oggetto da misurare 08: @param anObject l'oggetto da misurare 09: @return la misura

09: @return la misura 10: */

10: */

11: double measure(Object anObject);

11: double measure(Object anObject);

12: } 12: }

(42)

42 42

RectangleMeasurer RectangleMeasurer

01: import java.awt.Rectangle;

01: import java.awt.Rectangle;

02:02:

03: /**

03: /**

04: Gli oggetti di questa classe misurano i rettengoli in 04: Gli oggetti di questa classe misurano i rettengoli in base all'area.

base all'area.

05: */

05: */

06: public class RectangleMeasurer implements Measurer 06: public class RectangleMeasurer implements Measurer 07: {

07: {

08: public double measure(Object anObject) 08: public double measure(Object anObject) 09: {

09: {

10: Rectangle aRectangle = (Rectangle) anObject;

10: Rectangle aRectangle = (Rectangle) anObject;

11: double area = aRectangle.getWidth() 11: double area = aRectangle.getWidth()

* aRectangle.getHeight();* aRectangle.getHeight();

12: return area;

12: return area;

13: } 13: } 14: } 14: } 15: 15:

(43)

43 43

RectangleMeasurer RectangleMeasurer

Average area = 616.6666666666666 Average area = 616.6666666666666

Maximum area rectangle = java.awt.Rectangle[x=10,y=20, Maximum area rectangle = java.awt.Rectangle[x=10,y=20, // width=30,height=40] // width=30,height=40]

 Output Output

(44)

44 44

Classi Interne Classi Interne

 Una classe semplice può essere definita all'interno di Una classe semplice può essere definita all'interno di un metodo

un metodo

public class DataSetTester3 public class DataSetTester3 { {

public static void main(String[] args) public static void main(String[] args)

{ {

class RectangleMeasurer implements Measurer class RectangleMeasurer implements Measurer

{ {

. . . . . .

} }

Measurer m = new RectangleMeasurer();

Measurer m = new RectangleMeasurer();

DataSet data = new DataSet(m); . . . DataSet data = new DataSet(m); . . .

} } } }

(45)

45 45

Classi Interne Classi Interne

 Se una classe interna viene definita all'interno del Se una classe interna viene definita all'interno del contesto di un'atra classe,

contesto di un'atra classe, ma al di fuori dei metodi, ma al di fuori dei metodi,

essa è visibile a tutti i metodi della classe esterna essa è visibile a tutti i metodi della classe esterna

 Il compilatore converte una classe interna in un Il compilatore converte una classe interna in un normale file di classe:

normale file di classe:

DataSetTester$1$RectangleMeasurer.class DataSetTester$1$RectangleMeasurer.class

(46)

46 46

Sintassi 11.3: Classi Interne Sintassi 11.3: Classi Interne

Dichiarata in un metodo Dichiarata in un metodo class

class NomeClasseEsterna NomeClasseEsterna { {

firma di metodofirma di metodo { {

. . .

class NomeClasseInterna class NomeClasseInterna

{ {

// metodi // metodi

// campi // campi

} }

. . . } }

. . . . . . } } 

Dichiarata in una classe Dichiarata in una classe class

class NomeClasseEsterna NomeClasseEsterna { {

// metodi // metodi

// campi // campi

accessSpecifier class accessSpecifier class

NomeClasseInternaNomeClasseInterna

{ {

// metodi // metodi

// campi // campi

} } . . . . . . }}

(47)

47 47

Sintassi 11.3: Classi Interne Sintassi 11.3: Classi Interne

 Esempio: Esempio:

public class Tester public class Tester { {

public static void main(String[] args) public static void main(String[] args) { {

class RectangleMeasurer implements Measurer class RectangleMeasurer implements Measurer

{ {

. . .

} }

. . . } }

}}

Scopo Scopo : definire una classe interna la cui visibilità è : definire una classe interna la cui visibilità è limitata a un singolo metodo o ai metodi di una

limitata a un singolo metodo o ai metodi di una singola classe

singola classe

(48)

48 48

FileTester3.java FileTester3.java

01: import java.awt.Rectangle;

01: import java.awt.Rectangle;

02: 02:

03: /**

03: /**

04: Questo programma mostra l'uso di Measurer.

04: Questo programma mostra l'uso di Measurer.

05: */

05: */

06: public class DataSetTester3 06: public class DataSetTester3 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: class RectangleMeasurer implements Measurer 10: class RectangleMeasurer implements Measurer 11: {

11: {

12: public double measure(Object anObject) 12: public double measure(Object anObject) 13: {

13: {

14: Rectangle aRectangle = (Rectangle) anObject;

14: Rectangle aRectangle = (Rectangle) anObject;

15: double area 15: double area

16: = aRectangle.getWidth() 16: = aRectangle.getWidth()

* aRectangle.getHeight();* aRectangle.getHeight();

17: return area;

17: return area;

(49)

49 49

FileTester3.java FileTester3.java

18: } 18: } 19: } 19: } 20: 20:

21: Measurer m = new RectangleMeasurer();

21: Measurer m = new RectangleMeasurer();

22: 22:

23: DataSet data = new DataSet(m);

23: DataSet data = new DataSet(m);

24: 24:

25: data.add(new Rectangle(5, 10, 20, 30));

25: data.add(new Rectangle(5, 10, 20, 30));

26: data.add(new Rectangle(10, 20, 30, 40));

26: data.add(new Rectangle(10, 20, 30, 40));

27: data.add(new Rectangle(20, 30, 5, 10));

27: data.add(new Rectangle(20, 30, 5, 10));

28: 28:

29: System.out.println("Average area = " + 29: System.out.println("Average area = " + data.getAverage());

data.getAverage());

30: Rectangle max = (Rectangle) data.getMaximum();

30: Rectangle max = (Rectangle) data.getMaximum();

31: System.out.println("Maximum area rectangle = " + max);

31: System.out.println("Maximum area rectangle = " + max);

32: } 32: } 33: } 33: }

(50)

50 50

Elaborare eventi di Elaborare eventi di

temporizzazione temporizzazione

 La classe La classe Timer Timer nel pacchetto nel pacchetto javax.swing javax.swing genera una sequenza di eventi, separati da intervalli genera una sequenza di eventi, separati da intervalli

di tempo tutti uguali fra loro di tempo tutti uguali fra loro

 Ciò è utile ogni volta si vuole disporre di oggetti Ciò è utile ogni volta si vuole disporre di oggetti aggiornati a intervalli regolari

aggiornati a intervalli regolari

 Un ricevitore di eventi ( Un ricevitore di eventi ( listener listener ) riceve una notifica ) riceve una notifica quando accade un particolare evento

quando accade un particolare evento

public interface ActionListener public interface ActionListener {{

   void actionPerformed(ActionEvent event);

   void actionPerformed(ActionEvent event);

} }

(51)

51 51

Elaborare eventi di Elaborare eventi di

temporizzazione temporizzazione

 Dovete definire una classe che realizzi l’interfaccia Dovete definire una classe che realizzi l’interfaccia ActionListener

ActionListener

class MyListener implements ActionListener class MyListener implements ActionListener {{

     void actionPerformed(ActionEvent event)      void actionPerformed(ActionEvent event)    {   {

      // questa azione verrà eseguita a ogni       // questa azione verrà eseguita a ogni

// evento di temporalizzazione// evento di temporalizzazione

Inserite qui le azioni del ricevitore di eventiInserite qui le azioni del ricevitore di eventi    }   }

}}

(52)

52 52

Elaborare eventi di Elaborare eventi di

temporizzazione temporizzazione

 Costruire un oggetto di tale classe e Costruire un oggetto di tale classe e passarlo al costruttore di

passarlo al costruttore di Timer Timer . .

MioRicevitore listener = new MioRicevitore listener = new MioRicevitore();

MioRicevitore();

Timer t = new Timer(interval, listener);

Timer t = new Timer(interval, listener);

t.start();

t.start();

(53)

53 53

Esempio: Temporizzatore Esempio: Temporizzatore

Esempio Esempio : un temporizzatore che conta all’indietro : un temporizzatore che conta all’indietro

Figura 3:

esecuzione del programma TimeTester

(54)

54 54

TimeTester.java TimeTester.java

01: import java.awt.event.ActionEvent;

01: import java.awt.event.ActionEvent;

02: import java.awt.event.ActionListener;

02: import java.awt.event.ActionListener;

03: import javax.swing.JOptionPane;

03: import javax.swing.JOptionPane;

04: import javax.swing.Timer;

04: import javax.swing.Timer;

05: 05:

06: /**

06: /**

07: Questo programma collauda la classe Timer.

07: Questo programma collauda la classe Timer.

08: */

08: */

09: public class TimerTester 09: public class TimerTester 10: {

10: {

11: public static void main(String[] args) 11: public static void main(String[] args) 12: {

12: {

13: class CountDown implements ActionListener 13: class CountDown implements ActionListener 14: {

14: {

15: public CountDown(int initialCount) 15: public CountDown(int initialCount) 16: {

16: {

17: count = initialCount;

17: count = initialCount;

18: } 18: }

(55)

55 55

TimeTester.java TimeTester.java

19: 19:

20: public void actionPerformed(ActionEvent event) 20: public void actionPerformed(ActionEvent event) 21: {

21: {

22: if (count >= 0) 22: if (count >= 0)

23: System.out.println(count);

23: System.out.println(count);

24: if (count == 0) 24: if (count == 0)

25: System.out.println("Liftoff!");

25: System.out.println("Liftoff!");

26: count--;

26: count--;

27: } 27: } 28: 28:

29: private int count;

29: private int count;

30: } 30: } 31: 31:

32: CountDown listener = new CountDown(10);

32: CountDown listener = new CountDown(10);

33: 33:

34: final int DELAY = 1000;

34: final int DELAY = 1000; // Millisecondi fra gli // Millisecondi fra gli

eventi eventi

(56)

56 56

TimeTester.java TimeTester.java

35: Timer t = new Timer(DELAY, listener);

35: Timer t = new Timer(DELAY, listener);

36: t.start();

36: t.start();

37: 37:

38: JOptionPane.showMessageDialog(null, "Quit?");

38: JOptionPane.showMessageDialog(null, "Quit?");

39: System.exit(0);

39: System.exit(0);

40: } 40: } 41: } 41: }

(57)

57 57

Accesso alle Variabili Circostanti Accesso alle Variabili Circostanti

 I metodi di una classe interna possono accedere alle I metodi di una classe interna possono accedere alle variabili dell’ambito di visibilità circostante.

variabili dell’ambito di visibilità circostante.

 Utile per la realizzazione di gestori di eventi, perché Utile per la realizzazione di gestori di eventi, perché consente alla classe interna di accedere alle variabili consente alla classe interna di accedere alle variabili

senza che ci sia bisogno di passarle come parametri senza che ci sia bisogno di passarle come parametri

 Esempio: Esempio:

utilizzare un temporizzatore per allestire un’animazione; utilizzare un temporizzatore per allestire un’animazione;

si sposterà una forma in una diversa posizione, dieci volte si sposterà una forma in una diversa posizione, dieci volte al secondo.

al secondo.

(58)

58 58

Accesso alle Variabili Circostanti Accesso alle Variabili Circostanti

class Mover implements ActionListener class Mover implements ActionListener { {

public void actionPerformed(ActionEvent event) public void actionPerformed(ActionEvent event) {

{

// sposta il rettangolo// sposta il rettangolo }

} } }

ActionListener listener = new Mover();

ActionListener listener = new Mover();

final int DELAY = 100;

final int DELAY = 100;

// Millisecondi fra due eventi di temporizzazione // Millisecondi fra due eventi di temporizzazione Timer t = new Timer(DELAY, listener);

Timer t = new Timer(DELAY, listener);

t.start();

t.start();

(59)

59 59

Accesso alle Variabili Circostanti Accesso alle Variabili Circostanti

 Il metodo Il metodo actionPerformed actionPerformed può accedere alle può accedere alle variabili che si trovano nell’ambito di visibilità

variabili che si trovano nell’ambito di visibilità circostante, in questo modo:

circostante, in questo modo:

public static void main(String[] args) public static void main(String[] args) { {

. . . . . .

final Rectangle box = new Rectangle(5, 10, 20, 30);

final Rectangle box = new Rectangle(5, 10, 20, 30);

class Mover implements ActionListener class Mover implements ActionListener {

{

public void actionPerformed(ActionEvent event) public void actionPerformed(ActionEvent event) {

{

// sposta il rettangolo// sposta il rettangolo box.translate(1, 1);

box.translate(1, 1);

} } } }

. . . . . . } }

(60)

60 60

Accesso alle Variabili Circostanti Accesso alle Variabili Circostanti

 Le variabili locali a cui si accede da un metodo di Le variabili locali a cui si accede da un metodo di una classe interna devono essere dichiarate

una classe interna devono essere dichiarate final final

 Una classe interna può accedere ai campi di Una classe interna può accedere ai campi di

esemplare della classe circostante, ma il campo esemplare della classe circostante, ma il campo

deve appartenere all’oggetto che ha costruito deve appartenere all’oggetto che ha costruito

l’esemplare della classe interna l’esemplare della classe interna

 Se l’esemplare di classe interna viene costruito Se l’esemplare di classe interna viene costruito all’interno di un metodo statico, può accedere all’interno di un metodo statico, può accedere

solamente alle variabili statiche della classe solamente alle variabili statiche della classe

circostante

circostante

(61)

61 61

TimeTester2.java TimeTester2.java

01: import java.awt.Rectangle;

01: import java.awt.Rectangle;

02: import java.awt.event.ActionEvent;

02: import java.awt.event.ActionEvent;

03: import java.awt.event.ActionListener;

03: import java.awt.event.ActionListener;

04: import javax.swing.JOptionPane;

04: import javax.swing.JOptionPane;

05: import javax.swing.Timer;

05: import javax.swing.Timer;

06: 06:

07: /**

07: /**

08: Questo programma utilizza un temporizzatore per spostare 08: Questo programma utilizza un temporizzatore per spostare

un rettangolo dieci volte al secondo.un rettangolo dieci volte al secondo.

09: */

09: */

10: public class TimerTester2 10: public class TimerTester2

11: { 11: {

12: public static void main(String[] args) 12: public static void main(String[] args)

13: { 13: {

14: final Rectangle box = new Rectangle(5, 10, 20, 30);

14: final Rectangle box = new Rectangle(5, 10, 20, 30);

15: 15:

16: class Mover implements ActionListener 16: class Mover implements ActionListener

17: { 17: {

(62)

62 62

TimeTester2.java TimeTester2.java

18: public void actionPerformed(ActionEvent event) 18: public void actionPerformed(ActionEvent event) 19: {

19: {

20: box.translate(1, 1);

20: box.translate(1, 1);

21: System.out.println(box);

21: System.out.println(box);

22: } 22: } 23: } 23: } 24: 24:

25: ActionListener listener = new Mover();

25: ActionListener listener = new Mover();

26: 26:

27: final int DELAY = 100;

27: final int DELAY = 100; // Millisecondi fra due eventi// Millisecondi fra due eventi

di temporalizzazionedi temporalizzazione 28: Timer t = new Timer(DELAY, listener);

28: Timer t = new Timer(DELAY, listener);

29: t.start();

29: t.start();

30: 30:

31: JOptionPane.showMessageDialog(null, "Quit?");

31: JOptionPane.showMessageDialog(null, "Quit?");

32: System.out.println("Last box position: " + box);

32: System.out.println("Last box position: " + box);

33: System.exit(0);

33: System.exit(0);

34: } 34: } 35: } 35: }

(63)

63 63

TimeTester2.java TimeTester2.java

java.awt.Rectangle[x=6,y=11,width=20,height=30]

java.awt.Rectangle[x=6,y=11,width=20,height=30]

java.awt.Rectangle[x=7,y=12,width=20,height=30]

java.awt.Rectangle[x=7,y=12,width=20,height=30]

java.awt.Rectangle[x=8,y=13,width=20,height=30] . . . java.awt.Rectangle[x=8,y=13,width=20,height=30] . . . java.awt.Rectangle[x=28,y=33,width=20,height=30]

java.awt.Rectangle[x=28,y=33,width=20,height=30]

java.awt.Rectangle[x=29,y=34,width=20,height=30]

java.awt.Rectangle[x=29,y=34,width=20,height=30]

Last box position:

Last box position:

java.awt.Rectangle[x=29,y=34,width=20,height=30]

java.awt.Rectangle[x=29,y=34,width=20,height=30]

 Visualizza: Visualizza:

Riferimenti

Documenti correlati

 la classe deve implementare tutti i metodi definiti nelle interfacce presenti in &lt;interfaceIdList&gt;. 

 la classe deve implementare tutti i metodi definiti nelle interfacce presenti in &lt;interfaceIdList&gt;. 

Il processo di trovare tutti i pixel che nel frame buffer appartengono alla primitiva è detto

™Una rotazione viene espressa come una serie di tre rotazioni sui tre assi. ™Deriva dal modo con cui si descrive l’orientamento di un

™Il processo di trovare tutti i pixel che nel frame buffer appartengono alla primitiva è detto

™ In un una pinhole camera è facile determinare come si forma l’immagine sul fondo della camera (piano della pellicola). ™ Il pinhole è detto

™Qual’e l’asse di rotazione per girare la testa in modo da guardare in basso a destra?.. 25 Nov 2002 Costruzione di Interfacce - Paolo Cignoni 13. Evitare il

Switch - Uno switch è un sistema che lavora a livello ISO 2, simile ad un hub ma è dotato di intelligenza per ottimizzare la comunicazione sulla rete: memorizza in una