programmazione con interfacce. scelta delle classi di un progetto criteri di coesione e...

123
Programmazione con Interfacce

Upload: abramo-stella

Post on 01-May-2015

217 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Programmazione conInterfacce

Page 2: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

• Scelta delle classi di un progetto Criteri di coesione e accoppiamento

• Interfacce Tipi, sottotipi e conversioni di tipo Polimorfismo e dinamic dispatch

• Interfacce come strumento di progetto Interfacce e riuso di codice Callbacks

• Classi interne

Page 3: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Organizzazione di una classe

public class ClassTemplate {

// costanti pubbliche

// costruttori pubblici

// metodi “accessors” pubblici

// metodi “mutators” pubblici

// campi privati

// classi interne e metodi ausiliari privati

}

Continua…

Page 4: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Organizzazione di una classe

• Visibilità dei campi: evitare campi pubblici Quando necessario, definite metodi per accedere e

modificare i campi

• Completezza dell’interfaccia pubblica Assicuratevi che l’interfaccia pubblica fornisca le

funzionalità necessarie per un utilizzo naturale ed efficace delle istanze

• Documentate il codice Non solo commenti (vedremo …)

Page 5: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Classi di un progetto• Una classe dovrebbe rappresentare un

concetto singolo, oppure un insieme di valori ben caratterizzato (un tipo)

• Concetti/tipi in matematica:Point, Rectangle, ..., Set, List, ...

• Concetti/tipi nella vita reale BankAccount, CashRegister, ...

Continua…

Page 6: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Classi di un progetto

• Una classe può anche identificare un insieme di “attori” oggetti che offrono un insieme di funzionalità

Scanner, RandomNumberGenerator

• Una classe può anche agire da contenitore di metodi e campi static (quindi una classe

senza istanze)

Math inizializzatore della computazione (mediante il main)

Page 7: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Coesione

• Una classe dovrebbe rappresentare un solo concetto

• L’interfaccia pubblica di una classe è coesa se tutte le sue componenti sono relative al concetto che la classe rappresenta

Continua…

Page 8: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Coesione

• Questo è un esempio di classe non coesa …

• Perché?

public class CashRegister{ public void enterPayment(int dollars, int quarters, int dimes, int nickels, int pennies) . . . public static final double NICKEL_VALUE = 0.05; public static final double DIME_VALUE = 0.1; public static final double QUARTER_VALUE = 0.25; . . .}

Continua…

Page 9: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Coesione• CashRegister coinvolge due concetti:

Registratore di cassa, monete

• Soluzione alternativa: due classi

public class Coin{ public Coin(double aValue, String aName){ . . . } public String getName(){ . . . } . . .}public class CashRegister{ public void enterPayment(Coin... coins) { . . . } . . .}

vararg

Page 10: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Accoppiamento (Coupling )• Una classe dipende da un’altra classe se

utilizza oggetti di quella classe CashRegister dipende da Coin per il calcolo della

somma del pagamento Coin non dipende CashRegister

Continua…

Page 11: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

UML

• Per visualizzare le relazioni tra classi utilizziamo diagrammi

• UML: Unified Modeling Language.

• Notazione standard per l’analisi ed il progetto di applicazioni software

Page 12: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Gradi di accoppiamento• Alto grado di accoppiamento implica molte

dipendenze tra classi

• Basso grado di accoppiamenento facilita manutenibilità in caso di modifica delle componenti (della loro interfaccia esterna)

Continua…

Page 13: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Gradi di accoppiamento

• Vedremo tecniche per bilanciare correttamente il grado di accoppiamento

Page 14: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce

• L’impiego di tipi interfaccia nel progetto di una applicazione rende il codice flessibile e robusto favorisce il riuso di codice permette di controllare il grado di accoppiamento tra

le componenti del progetto

• Esempio: definiamo una classe DataSet che permette di condurre alcune semplici analisi su un insieme di dati numerici calcolo della media calcolo del valore massimo Continua…

Page 15: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

DataSetpublic class DataSet { public void add(double x) { sum = sum + x; if (count == 0 || maximum < x) maximum = x; count++; } public double getMaximum(){ return maximum; } public double average() { return (count>0)? sum/count : Double.NaN; } private double sum; private double maximum; private int count; }

Page 16: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce

• Ora supponiamo di voler condurre le stesse analisi su un insieme di conti bancari per

• tracciare la media degli importi del saldo• calcolare il conto con il saldo massimo.

monete per • calcolare l taglio medio delle monete• determinare il taglio massimo

• La struttura della classe è sempre la stessa, ma il codice cambia …

Continua…

Page 17: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

DataSet – versione per BankAccount

public class DataSet { public void add(BankAccount x) { sum = sum + x.getBalance(); if (count == 0 || maximum.getBalance() < x.getBalance()) maximum = x; count++; } public BankAccount getMaximum() { return maximum; } public double average() {return (count>0)? sum/count : Double.NaN; } private double sum; private BankAccount maximum; private int count; }

Page 18: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

DataSet – versione per Coinpublic class DataSet { public void add(Coin x) { sum = sum + x.getValue(); if (count == 0 || maximum.getValue() < x.getValue()) maximum = x; count++; }

public Coin getMaximum() { return maximum; } public double average() {return (count>0)? sum/count : Double.NaN; } private double sum; private Coin maximum; private int count; }

Page 19: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce riuso di codice

• Il meccanismo di analisi dei dati è sempre lo stesso; la differenza è solo nel metodo che estrae i valori

• E se le diverse classi si uniformassero nell’uso di uno stesso metodo, getMeasure() per fornire la misura?

• In quel caso potremmo definire una sola versione di DataSet con un metodo add() come il seguente

Continua…

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

Continua…

Page 20: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce riuso di codice

• Quale è il tipo della variabile x a questo punto?

• Idea: il tipo di una qualunque classe che fornisca un metodo getMeasure

• In Java usiamo tipi interfaccia

• Una dichiarazione di interfaccia include tutti i metodi (le loro firme) che intendiamo attribuire al tipo interfaccia corrispondente

public interface Measurable { double getMeasure(); }

Page 21: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

DataSet – versione generica

public class DataSet { public void add(Measurable x) { sum = sum + x.getMeasure(); if (count == 0 || maximum.getMeasure() < x.getMeasure()) maximum = x; count++; } public Measurable getMaximum() { return maximum; } public double average() { return sum/count; } private double sum; private Measurable maximum; private int count; }

Page 22: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Classi vs. Interfacce

• Un tipo interfaccia è simile ad un tipo classe, ma ci sono molte differenze importanti:

• I metodi (tutti) dell’interfaccia sono “astratti” L’interfaccia non definisce una implementazione

• Tutti i metodi di una interfaccia sono automaticamente pubblici

• Una interfaccia non ha campi (mentre può avere campi statici, ovvero costanti)

Page 23: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Classi implementano Interfacce• La keyword implements indica che una classe

implementa una interfaccia

• Una classe può implementare più interfacce La classe deve implementare tutti i metodi di tutte le

interfacce che implementa tutti questi metodi devono essere public nella classe

public class BankAccount implements Measurable { public double getMeasure() { return balance; } // altri metodi, campi e quant’altro ... }

Continua…

Page 24: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Classi implementano Interfacce

• Measurable Coins

public class Coin implements Measurable { public double getMeasure() { return value; } // . . . }

Page 25: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Diagrammi UML

• Notazione: Le interfacce sono rappresentate utilizzando

• la tag «interface» associata al nome• oppure indicando il nome in corsivo• La relazione tra una interfaccia ed una classe che

la implementa è rappresentata da una freccia tratteggiaga (dalla classe all’interfaccia)

Notazione simile alla dipendenza: cambia la punta della freccia

Continua…

Page 26: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Diagramma UML per l’esempio

dipende

implementa

Page 27: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Diagrammi UML

• L’impiego di interfacce riduce il numero di classi ed il grado di accoppiamento tra le classi

• Notate infatti che DataSet è disaccoppiata da BankAccount e Coin

• Possiamo liberamente modificare le classi basta che implementino correttamente l’interfaccia

Page 28: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Sintassi: definizione di interfaccia

public interface InterfaceName { // firme e contratti per i metodi }

Esempio: public interface Measurable { double getMeasure(); }

Scopo:Definire le firme ed i contratti per i metodi di un tipo interfaccia. Tutti i metodi sono automaticamente pubblici.

Page 29: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Sintassi: dichiarazione di classe

 public class ClassName implements InterfaceName, InterfaceName, ... { // ... }

Eesmpio: public class BankAccount implements Measurable { //... public double getMeasure() { // Method implementation } }

Scopo:Fornire una implementazione per il tipo interfaccia

Page 30: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSetTester.java01: /**02: This program tests the DataSet class.03: */04: public class DataSetTester05: {06: public static void main(String[] args)07: {08: DataSet bankData = new DataSet();09: 10: bankData.add(new BankAccount(0));11: bankData.add(new BankAccount(10000));12: bankData.add(new BankAccount(2000));13: 14: System.out.println("Average balance = " 15: + bankData.getAverage());16: Measurable max = bankData.getMaximum();17: System.out.println("Highest balance = " 18: + max.getMeasure()); Continua…

Page 31: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSetTester.java

19: 20: DataSet coinData = new DataSet();21: 22: coinData.add(new Coin(0.25, "quarter"));23: coinData.add(new Coin(0.1, "dime"));24: coinData.add(new Coin(0.05, "nickel"));25: 26: System.out.println("Average coin value = " 27: + coinData.getAverage());28: max = coinData.getMaximum();29: System.out.println("Highest coin value = " 30: + max.getMeasure());31: }32: }

Continua…

Page 32: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSetTester.java

Average balance = 4000.0 Highest balance = 10000.0 Average coin value = 0.13333333333333333 Highest coin value = 0.25

Output:

Page 33: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Vogliamo utilizzare la classe DataSet per trovare l’istanza di una classe Country con la popolazione maggiore in un insieme. Quali condizioni deve soddisfare la classe Country?

Page 34: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Cosa c’è di sbagliato nel seguente codice?

public void add(Object x){ sum = sum + x.getMeasure(); if (count == 0 || maximum.getMeasure() < x.getMeasure()) maximum = x; count++; }

Page 35: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Deve implementare l’interfaccia Measurable ed il suo metodo getMeasure() deve restituire il valore della popolazione

Page 36: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• La classe Object non ha un metodo getMeasure(), che viene invocato all’interno del metodo add()

Page 37: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Conversioni di tipo

• Variabile: locazione con un tipo associato Tipo della variabile determinato dal compilatore

guardando la dichiarazione Una variabile di tipo reference contiene un riferimento

ad un oggetto

• Oggetto: istanza di una classe Tipo dell’oggetto: la classe che lo crea Determinato a run time

• Una variabile può assumere come valori riferimenti ad oggetti di classi diverse

Continua…

Page 38: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Conversioni di tipo

• È possibile assegnare un riferimento di tipo classe ad una variabile di tipo interfaccia purchè la classe implementi l’interfaccia

BankAccount account = new BankAccount(10000);Measurable x = account; // OK

Coin dime = new Coin(0.1, "dime");Measurable y = dime; // OK

Continua…

Page 39: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Conversioni di tipo

• La conversione è lecita solo in determinate situazioni

• Problema: Rectangle non implementa Measurable

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

Page 40: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Subtyping

• Subtyping (<:) Una relazione che permette di decidere quando è

legittimo convertire un tipo riferimento in un altro

• Chi decide cosa/quando è legittimo? il compilatore!

• Per il momento la regola è:

Continua…

T1 <: T2 sse T1 è una classe, T2 è una interfaccia T1 implementa T2.

Page 41: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Subtyping

• Principio di sostituibilità Un riferimento di un sottotipo può essere usato

ovunque ci si aspetti un riferimento di un supertipo

• Le regole di sottotipo devono garantire la correttezza del principio di sostituibilità

Continua…

Page 42: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Subtyping

• La regola C <: I se C implementa I

• Principio di sostituibilità un riferimento di tipo C può sempre essere usato dove

si attende un riferimento di tipo I

• E’ ragionevole perché se C implementa I , C definisce public tutti i metodi

dichiarati da I Quindi tutti le invocazioni di metodo possibili per I sono

supportate da C

Continua…

Page 43: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Subtyping e regole di typing

• Regola di assegnamento Un riferimento di tipo T1 si puo sempre assegnare ad una variabile

di tipo T2 sse T1 <: T2 Un riferimento di tipo classe può sempre essere assegnato ad una

variabile di tipo interfaccia (se la classe implementa l’interfaccia)

• Regola di passaggio di parametri Un riferimento di tipo T1 si puo sempre passare per un parametro

di tipo T2 sse T1 <: T2 Un riferimento di tipo classe può sempre essere passato per un

parametro di tipo interfaccia (se la classe implementa l’interfaccia)

Page 44: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Data l’implementazione generica della classe DataSet, che oggetti possiamo passare come argomento per x ?

public class DataSet { public void add(Measurable x) { ... }

... }

Page 45: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Qualunque istanza di una una classe che implementa Measurable

Page 46: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• Consideriamo

• Cosa possiamo fare con max?

• Certamente non sapere quale moneta è …

DataSet coinDS = new DataSet();coinDS.add(new Coin(0.25, "quarter"));coinDS.add(new Coin(0.1, "dime"));. . .Measurable max = coinDS.getMaximum();

String name = max.getName(); // ERRORE: Non ha tipo Coin

Continua…

Page 47: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• Noi sappiamo che max è un riferimento di tipo Coin, ma il compilatore no.

• Dobbiamo usare un cast per convertire il tipo interfaccia nel tipo classe

• Ora usiamo maxCoin come desiderato

Coin maxCoin = (Coin) max;

Measurable max = coinDS.getMaximum();

Continua…

String name = maxCoin.getName();

Page 48: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• Un cast è permesso dal compilatore solo se applica conversioni tra tipi compatibili

• Compatibili = sottotipi (per il momento)

• Anche quando permesso dal compilatore, un cast può causare errore a run time

• Se max non è un Coin errore a run time

Continua…

Coin maxCoin = (Coin) max;

Page 49: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• Tipo statico e tipo dinamico di una variabile tipo statico: quello dichiarato tipo dinamico: il tipo del riferimento assegnato alla

variabile

• (T)var causa errore in compilazione

se T non è compatibile con il tipo statico di var in esecuzione

se T non è compatibile con il tipo dinamico di var

Continua…

Page 50: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• OK: BankAccount sottotipo di Measurable

• Compila correttamente il tipo dichiarato di m è Measurable BankAccount e Measurable sono compatibili

• Esegue correttamente m è un BankAccount (il tipo dinamico di m è BankAccount)

Measurable m = new BankAccount();

Continua…

BankAccount b = (BankAccount) m

Page 51: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Cast

• OK: BankAccount sottotipo di Measurable

• Compila correttamente il tipo dichiarato di m è Measurable Coin e Measurable sono compatibili

• Errore a run time m non è un Coin

Measurable m = new BankAccount();

Continua…

Coin c = (Coin) m

Page 52: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

instanceof

• Permette di determinare il tipo dinamico di una variabile

• Quindi permette di evitare errori in esecuzione

• Esegue correttamente, perchè x è sicuramente un T

x istanceof T è true solo se x ha tipo dinamico T

if (x instanceof T) return (T) x

Page 53: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Dato che sia BankAccount che Coin implementano l’interfaccia Measurable, è possibile convertire un riferimento di tipo Coin ad uno di tipo BankAccount?

Page 54: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• No: un riferimento di tipo Coin può essere convertito a Measurable, ma se poi tentiamo di applicare un cast a BankAccount, abbiamo una eccezione.

Page 55: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• E’ corretto un cast (BankAccount) x per convertire una variabile x di tipo dichiarato Measurable ad un riferimento di tipo BankAccount?

Page 56: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Solo se x contiene effettivamente un riferimento ad un oggetto di tipo BankAccount.

Page 57: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Polimorfismo – dynamic dispatch

• Una variabile di tipo interfaccia ha sempre come valore un riferimento di una classe che implementa l’interfaccia

Continua…

Measurable x;x = new BankAccount(10000);x = new Coin(0.1, "dime");

Page 58: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Polimorfismo – dynamic dispatch

• Possiamo invocare ognuno dei metodi dell’interfaccia:

• Quale metodo invoca?

double m = x.getMeasure();

Page 59: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Polimorfismo – dynamic dispatch

• Dipende dal riferimento corrente memorizzato nella variabile 

• Se x riferisce un BankAccount, invoca il metodo BankAccount.getMeasure()

• Se x riferisce un Coin, invoca il metodo Coin.getMeasure()

• Polimorfismo (molte forme): il comportamento varia, e dipende dal tipo dinamico

della variabile

Continua…

Page 60: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Polimorfismo – dynamic dispatch

• Detto anche late binding: deciso a tempo di esecuzione

• Diverso dal caso dell’overloading: Anche nel caso dell’overloading si deve decidere

quale versione del metodo invocare Ma qui la decisione viene risolta in compilazione

(early binding)

Page 61: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domande

5. È impossibile costruire un oggetto di tipo Measurable.Perché?

6. Perché invece é possibile dichiarare una variabile di tipo Measurable?

Page 62: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposte

5. Measurable è una interfaccia. Le interfacce non hanno campi o implementazione di metodo.

6. Perché Measurable è un tipo: la variabile non riferirà mai una istanza di Measurable, (le interfacce non hanno istanze) ma piuttosto oggetto di una qualche classe che implementa l’interfaccia Measurable.

Continua…

Page 63: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

7. Che cosa hanno in comune i meccanismi di overloading e di dynamic dispatch? In cosa sono diversi?

Page 64: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

7. Entrambi i meccanismi decidono quale metodo eseguire in risposta ad un messaggio, ma• Nell’overloading la scelta è fatta in compilazione

guardando il tipo dei parametri• Nel dynamic dispatch la scelta è fatta in esecuzione

guardando il tipo dell’oggetto che riceve il messaggio

Risposte

Page 65: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

• Costruiamo una applicazione per disegnare un insieme di forme geometriche contenute in una componente grafico: definiamo una JComponent contenitore per un

insieme di forme geometriche disegnate mediante una invocazione del metodo paintComponent()

per esemplificare, consideriamo due tipi di forme: Car e Smiley

Esempio

Page 66: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Forme grafiche

class Car{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }} class Smiley

{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }}

Page 67: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

• Un contenitore di Cars e Smileys

• Un caso particolare di JComponent

ShapeComponent

/** Una component che contiene un insieme Cars e Smileys */ class ShapeComponent extends JComponent { /** Disegna tutte le forme di questo component */ public void paintComponent(Graphics g){ /* ... */ } }

Page 68: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Che struttura utilizziamo per memorizzare le forme contenute nella ShapeComponent?

• Come definiamo il metodo paintComponent() in modo che disegni tutte le forme della componente?

Page 69: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposte

ArrayList:

• definiamo una nuova interfaccia: Shape

• Ridefiniamo le classi Car e Smiley in modo che implementino Shape

• Memorizziamo gli oggetti della componente in una ArrayList<Shape>

interface Shape { void draw(Graphics2D g); }

Page 70: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Car e Smiley implementano Shape

class Car implements Shape

{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }} class Smiley implements Shape

{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }}

Page 71: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Mantiene una ArrayList<Shape>

ShapeComponent

// Una component che contiene un insieme formeclass ShapeComponent extends JComponent { private ArrayList<Shape> shapes;

// crea una componente con un insieme di forme public ShapeComponent(Shape... shapes) {

this.shapes = new ArrayList<Shape>(); for (Shape s:shapes) this.shapes.add(s); } // disegna tutte le componenti della componente public void paintComponent(Graphics2D g2){

for (Shape c:shapes) c.draw(g2); } }

Page 72: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Diagramma delle Classi

Car

ShapeComponent

Smiley

Shape

Car

Page 73: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• E se volessimo disegnare solo le Shapes che sono Cars?

Page 74: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

// disegna tutte le cars della componente public void paintComponent(Graphics g){

Graphics2D g2 = (Graphics2D) g; for (Shape c:shapes)

if (c instanceof Car) c.draw(g2); }

Page 75: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce e “callbacks”

• La tecnica che abbiamo visto funziona per classi di cui abbiamo il controllo Nel caso delle forme geometrice, possiamo rendere Car e Smiley implementazioni di Shape

Nel caso del DataSet rendiamo Measurable le classi Coin e BankAccount

• Che facciamo se non possiamo modificare la definizione delle classi?

Continua…

Page 76: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce e “callbacks”

Esempio:

• Vogliamo misurare l’area media e l’area massima di un insieme di Rectangles

• Rectangle è una classe predefinita, e non implementa Measurable …

Continua…

Page 77: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce e “callbacks”

• Callback: tradizionalmente (*) indica un meccanismo per passare ad una funzione un’altra funzione che esegue una qualche operazione specifica

• La funziona passata come argomento si definisce callback

(*) almeno dai tempi del progetto MIT che diede luogo a X (meglio noto com X11) … correva l’anno 1984

Continua…

Page 78: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce e “callbacks”

Esempio classico:

• una funzione che gestisce le scelte di un menù

• definita in termini di un parametro di tipo funzione che viene invocata per gestire l’operazione da eseguire in risposta alla selezione degli items del menù

• Il parametro è una callback

Continua…

Page 79: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Interfacce e “callbacks”

• Nei linguaggi ad oggetti non possiamo passare parametri di tipo funzione

• In C# esiste un costrutto predefinito che realizza questo meccanismo: i delegates

• In Java il meccanismo può essere simulato definiamo una classe con un metodo che implementa

la funzione callback passiamo un oggetto di quella classe e lo utilizziamo

per invocare la callback

Page 80: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks per DataSet

• Problema: misurare l’area media e l’area massima di un insieme di Rectangles

• Nell’implementazione vista, gli oggetti da misurare offrono direttamente il metodo che misura

• Alternativa: passiamo alla classe DataSet un metodo per misurare oggetti

Continua…

Page 81: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

• measure() misura qualunque oggetto e Measurer rappresenta qualunque classe lo definisca

• Object è il supertipo di tutti i tipi riferimento

• qualunque riferimento si può passare per un parametro di tipo Object

public interface Measurer { double measure(Object anObject); }

Callbacks per DataSet

Continua…

Page 82: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks per DataSet

• La classe DataSet diventa dipendente dal metodo di misura, ovvero da qualunque classe che definisca questo metodo

public class DataSet { ... public DataSet(Measurer aMeasurer) {

measurer = aMeasurer; } ... private Measurer measurer;}

Continua…

Page 83: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks per DataSet

• Ora il metodo add() richiede la misura al measurer non all’oggetto che viene incluso nel dataset.

public void add(Object x) { sum = sum + measurer.measure(x); if (count == 0 || measurer.measure(maximum) < measurer.measure(x)) maximum = x; count++; }

Continua…

Page 84: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks per DataSet

• Possiamo definire Measurers per qualunque tipo di misura, in particolare per misurare Rectangles

public class RectangleMeasurer implements Measurer { public double measure(Object anObject) { if (!anObject instanceof Rectangle) return Double.NaN; Rectangle aRectangle = (Rectangle) anObject; double area = aRectangle.getWidth() * aRectangle.getHeight(); return area; } }

Continua…

Page 85: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks per DataSet

• Notiamo il cast da Object a Rectangle

• Passiamo il measurer desiderato al momento della costruzione del dataset

• Dynamic dispatch => invochiamo l’implementazione di measure() fornita da RectangleMeasurer

Rectangle aRectangle = (Rectangle) anObject;

Measurer m = new RectangleMeasurer();DataSet data = new DataSet(m);data.add(new Rectangle(5, 10, 20, 30));. . .

Continua…

Page 86: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Diagramma delle classi

• Notate che la classe Rectangle è disaccoppiata dall’interfaccia Measurer

double measure(Object o)

Page 87: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Raffronto tra le due soluzioni

• Callbacks Measurer

double measure(Object o)

Rectangle

double getMeasure()

• Oggetti Measurable

Page 88: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSet.java01: /**02: Calcola la media di un insieme di oggetti.03: */04: public class DataSet05: {06: /**07: Costruisce un insieme vuoto con un dato misuratore.08: @param aMeasurer il misuratore utilizzato per misurare i valori09: */10: public DataSet(Measurer aMeasurer)11: {12: sum = 0;13: count = 0;14: maximum = null;15: measurer = aMeasurer;16: }17: Continua…

Page 89: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSet.java18: /**19: aggiunge un valore al dataset.20: @param x un dato21: */22: public void add(Object x)23: {24: sum = sum + measurer.measure(x);25: if (count == 0 26: || measurer.measure(maximum) < measurer.measure(x))27: maximum = x;28: count++;29: }30: 31: /**32: Calcola la media dei dati considerati.33: @return la media o 0 se l’insieme di dati è vuoto34: */

Continued…

Page 90: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSet.java

35: public double average()36: {37: if (count == 0) return 0;38: else return sum / count;39: }40: 41: /**42: Il massimo del dataset.43: @return il massimo o 0 se non il dataset è vuoto44: */45: public Object maximum()46: {47: return maximum;48: }49: Continua…

Page 91: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSet.java

50: private double sum;51: private Object maximum;52: private int count;53: private Measurer measurer;54: }

Page 92: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSetTester.java

01: import java.awt.Rectangle;02: 03: /**04: Dimostra l’uso del misuratore.05: */06: public class DataSetTester07: {08: public static void main(String[] args)09: {10: Measurer m = new RectangleMeasurer();11: 12: DataSet data = new DataSet(m);13: 14: data.add(new Rectangle(5, 10, 20, 30));15: data.add(new Rectangle(10, 20, 30, 40));16: data.add(new Rectangle(20, 30, 5, 10));17: Continua…

Page 93: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File DataSetTester.java

18: System.out.println("Average area = " + data.getAverage());19: Rectangle max = (Rectangle) data.getMaximum();20: System.out.println("Maximum area rectangle = " + max);21: }22: }

Page 94: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File Measurer.java

01: /**02: Interfaccia di qualunque classe le cui istanze misurano

altri oggetti.03: */04: public interface Measurer05: {06: /**07: Calcola la misura di un oggetto.08: @param anObject l’oggetto da misurare09: @return la misura10: */11: double measure(Object anObject);12: }

Page 95: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File RectangleMeasurer.java01: import java.awt.Rectangle;02:03: /**04: le istanze di questa classe misurano l’area di un rettangolo05: */06: public class RectangleMeasurer implements Measurer07: {08: public double measure(Object anObject)09: {10: Rectangle aRectangle = (Rectangle) anObject;11: double area = aRectangle.getWidth() * aRectangle.getHeight();12: return area;13: }14: }15:

Continua…

Page 96: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File RectangleMeasurer.java

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

Output:

Page 97: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Supponiamo di voler utilizzare la prima versione della classe DataSet per trovare la Stringa più lunga di un insieme dato in input. Quale è il problema?

Page 98: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Problema: la classe String non implementa Measurable.

Page 99: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Come possiamo utilizzare la seconda versione di DataSet (con callbacks) per risolvere il problema precedente?

Page 100: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Definendo una classe StringMeasurer che implementa l’interfaccia Measurer

Page 101: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Perchè il metoto measure() dell’interfaccia Measurer ha un parametro in più del metodo getMeasure() dell’interfaccia Measurable?

Page 102: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• measure() misura un oggetto, passato come argomento, mentre getMeasure() misura this, ovvero il parametro implicito.

Page 103: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Esercizio

• Definiamo una nuova versione della classe DataSet che sia utilizzabile sia su oggetti generici, mediante un Measurer, sia su oggetti Measurable.

• Il comportamento del metodo add() dipende dal tipo dell’argomento: se il tipo è Measurable, l’argomento viene misurato

utilizzando il suo metodo getMeasure() in tutti gli altri casi, viene misutato dal Measurer del

data set

Page 104: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Callbacks nella gestione di un timer

• La classe javax.swing.Timer definisce oggetti che generano eventi (ticks)

• Utile tutte le volte che vogliamo modificare un oggetto ad intervalli di tempo regolari

• Ad esempio nelle animazioni: Smiley: modifica il saluto oppure l’espressione Car: si muove sul frame ad intervalli regolari

Continua…

Page 105: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Gestione di un timer

• Eventi notificati ad un “Action Listener” associato al timer

• Action Listener descritto da una interfaccia standard (predefinita)

actionPerformed() invocato ad ogni tick event: contiene informazione sull’evento

public interface ActionListener{   void actionPerformed(ActionEvent event);}

Continua…

Page 106: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Gestione di un timer

• La gestione dell’evento avviene nel metodo actionPerformed()

• Gestioni diverse realizzate da classi diverse che implementano ActionListener

class MyListener implements ActionListener{     public void actionPerformed(ActionEvent event)    {      // Eseguito ad ogni tick.     }}

Continua…

Page 107: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Gestione di un timer

• Per associare un particolare listener al timer è necessario registrare il listener sul timer

• Ora possiamo far partire il timer

MyListener listener = new MyListener();Timer t = new Timer(interval, listener);

t.start(); // Esegue in un thread separato

tra due tick

Page 108: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Quale è il ruolo del listener nel timer?

Page 109: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Il listener implementa una callback: il metodo actionPerformed() è la vera callback che viene inclusa nel listener per poter essere passata al controllore del timer che la invoca ad ogni tick

Page 110: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Esempio: conto alla rovescia

• Un timer che esegue il countdown

Page 111: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File CountDown.java

class CountDown implements ActionListener{ public CountDown(int initialCount) {

count = initialCount; } public void actionPerformed(ActionEvent event){}

public void actionPerformed() {

if (count >= 0) System.out.println(count);if (count == 0) System.out.println("Liftoff!");count--;

} private int count;}

Continua…

Page 112: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

File TimeTester.java

import java.awt.event.*;import javax.swing.*;/** Esemplifica la classe timer l’uso di action listeners.*/public class TimeTester{ public static void main(String[] args) { CountDown listener = new CountDown(10); final int DELAY = 1000;// Millisecondi tra due tick Timer t = new Timer(DELAY, listener); t.start();

JOptionPane.showMessageDialog(null, "Quit?"); System.exit(0); }}

Page 113: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Domanda

• Quante volte viene chiamato il metodo actionPerformed nel programma precedente?

Page 114: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Risposta

• Il metodo viene invocato una volta al secondo. Le prime 11 volte scrive un messaggio. Le successive termina senza output,

decrementando il contatore. Il timer termina quando l’utente chiude l’applicazione

Page 115: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

NOTE

• Tutti gli eventi del timer vengono gestiti dallo stesso thread (l’Event Dispatch Thread) se la gestione dell’evento richiede più tempo

dell’intervallo, gli eventi vengono persi

• Informazione sull’utilizzo di timers in swing: http://java.sun.com.j2se/1.5.0/docs/api/javax/swing/

Timer.html

Page 116: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Packages

• Package: insieme di classi e interfacce in relazione

• Per formare un package basta inserire la direttiva

come prima istruzione nel file sorgente

• Una sola direttiva per file

• Classi contenute in file che non dichiarano packages vengono incluse in un package “anonimo” package anonimo OK solo per micro applicazioni, o in fase di

sviluppo

package packageName;

Continua…

Page 117: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Package Finalità Classe Tipicajava.lang Supporto al linguaggio Math, String

java.util Utilities Random

java.io Input e Output PrintStream

Java.awt Abstract Window Toolkit Color

Java.applet Applets Applet

Java.net Networking Socket

Java.sql Accesso a database ResultSet

Java.swing Ingerfaccia utente Swing JButton

… … …

Packages

Page 118: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

• Per accedere ai tipi di un package utilizziamo il nome “qualificato”

• Uso dei nomi qualificati verboso

• import permette sintesi

java.util.Scanner in = new java.util.Scanner(System.in);

import java.util.Scanner;. . .Scanner in = new Scanner(System.in)

Accesso agli elementi di un package

Page 119: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Import

• di una classe

• di tutte le classi di un package

import java.util.*;

import java.util.Scanner;. . .Scanner in = new Scanner(System.in)

Continua…

Page 120: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Import

• Packages non formano gerarchie

• Static import delle costanti e metodi statici dei tipi di un package

// import dei tipi di java.awt.color

import java.awt.color.*;

// import dei tipi di java.awt (non del package color!)

import java.awt.*;// import dei tipi di java.awt.

import static java.lang.Math.PI

import static java.lang.Math.*;.

Page 121: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Nomi di package

• Packages utili anche come “namespaces” per evitare conflitti di nomi (per classi/interfacce)

• Esempio, Java ha due classi Timer

• Nomi di package devono essere univoci Convenzione: utilizziamo come prefissi domini

internet, oppure indirizzi e-mail (in ordine inverso)

java.util.Timer vs. javax.swing.Timer

it.unive.dsiit.unive.dsi.mp

Continua…

Page 122: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Localizzazione di package

• Nomi di package devono essere consistenti con i path della directory che li contengono

• Deve essere contenuto in un folder/directory localizzato nel path corrispondente

WINDOWS: <base directory>\it\unive\dsi\mp\banking

it.unive.dsi.mp.banking

UNIX: <base directory>/it/unive/dsi/mp/banking

Continua…

Page 123: Programmazione con Interfacce. Scelta delle classi di un progetto Criteri di coesione e accoppiamento Interfacce Tipi, sottotipi e conversioni di tipo

Localizzazione di package

• CLASSPATH: definisce le directory base dove localizzare i packages

• Spesso utili due directory base per file sorgenti (.java) per file compilati (.class)

UNIX:export CLASSPATH=/home/mp/java/src:/home/mp/java/classes:.

WINDOWS:set CLASSPATH=c:\home\mp\java\src;\home\mp\java\classes;.