Gerarchie di Tipi
Metodologie di progetto Estensione di classi Implementazione di interfacce Composizione
Notazione UML RelazioneSimboloSignificato Ereditarietàis-a Implementazioneis-a Aggregazionehas a Dipendenzausa
Una struttura universitaria Il personale è strutturato in Personale Docente: Faculty Personale Tecnico Amministrativo: Staff
Una struttura universitaria Introduciamo una terza categoria che descrive le due tipologie di personale UnivEmployee Definisce le caratteristiche di struttura e comportamento comuni a tutto il personale Intesa non per creare istanze proprie definiamo abstract per realizzare queste scelte di progetto
Una struttura universitaria UnivEmployee FacultyStaff
University Employees A tutto il personale viene garantito luso di posta elettronica Rappresentiamo mediante un metodo Includiamo il metodo in UnivEmployee così che venga ereditato dalle due classi derivate /** * manda un messaggio alloggetto su cui è invocato */ public void mailTo(String msg);
public abstract class UnivEmployee { private List mailbox = new ArrayList (); public void mailTo(String msg) { mailbox.add(msg); }... } public class Faculty extends UnivEmployee {... } public class Staff extends UnivEmployee {... } University Employees
Laccesso alla posta elettronica è una proprietà generale Possiamo concettualizzare questa proprietà una interfaccia University Employees interface Int { public void mailTo(String msg); }
University Employees con UnivEmployee FacultyStaff Int
abstract class UnivEmployee implements Int {... public void mailTo(String msg) {... } } class Faculty extends UnivEmployee {... } class Staff extends UnivEmployee {... } University Employees con
University Employees Al personale docente viene inoltre garantita la possibilità di gestire una propria pagina web Definito solo per la classe Faculty /** * restituisce la URL associata alloggetto */ public Url browse();
University Employees … on the web Anche qui, possiamo generalizzare introducendo una nuova interfaccia interface WebInt { public Url browse(); }
UnivEmployee FacultyStaff Int WebInt University Employees … on the web
public abstract class UnivEmployee implements Int {... public void mailTo(String msg) {... } } public class Faculty extends UnivEmployee implements WebInt { public Url browse() {... }... } public class Staff extends UnivEmployee {... } University Employees … on the web
Gerarchie di tipi Ogni classe può implementare più interfacce estendere al più una classe I due meccanismi si possono combinare
Gerarchie di tipi Uno schema ricorrente SuperClasse Classe Interfaccia Permette di utilizzare Classe come SuperClasse e Interfaccia
University Employees … on the web Possiamo dare struttura alla composizione di interfacce Estensione di interfacce no vincoli: possiamo estendere più di una interfaccia interfaccia che estende è sottotipo di tutte le interfacce che vengono estese interface Online extends Int,WebInt { }
UnivEmployee FacultyStaff Int WebInt University Employees … on-line OnLine
public abstract class UnivEmployee implements Int {... public void mailTo(String msg) {... } } public class Faculty extends UnivEmployee implements OnLine { public Url browse() {... }... } public class Staff extends UnivEmployee {... } University Employees … on line
Corsi Il personale docente insegna uno o più corsi allinterno dei corsi di laurea Rappresentiamo nei diagrammi con una nuova relazione tra classi associazione
University Employees UnivEmployee FacultyStaff Int WebInt Course 1..* OnLine
public abstract class UnivEmployee implements Int {... public void mailTo(String msg) {... } } public class Faculty extends UnivEmployee implements OnLine { public Url browse() {... }... private ArrayList courses;... } public class Staff extends UnivEmployee {... } University Employees
I corsi vengono gestiti dal personale tecnico amministrativo per gli aspetti relativi a iscrizione, liste di esami … La classe Staff dipende quindi dalla classe Course
University Employees UnivEmployee FacultyStaff Int WebInt Course 1..* OnLine
public abstract class UnivEmployee implements Int {... public void mailTo(String msg) {... } } public class Faculty extends UnivEmployee implements Online { public Url browse() {... }... private ArrayList courses;... } public class Staff extends UnivEmployee { public void admin(Course c) {... }... } University Employees
Corsi … on-line Possiamo sfruttare la struttura in più che abbiamo ottenuto dallintroduzione delle interfacce per rappresentare ulteriori funzionalità Ad esempio, i corsi possono essere dotati di un sito web e di un indirizzo di posta elettronica
Corsi … on-line UnivEmployee FacultyStaff Int WebInt Course 1..* OnLine
Metodologie di progetto basate su estensione e composizione di classi e interfacce Progetto di interfacce grafiche
Eventi e Listeners La sorgente di un evento ispeziona la lista dei suoi listeners (registrati) seleziona tutti i listeners il cui tipo corrisponde al tipo dellevento. su ciascuno dei listeners selezionati, invoca il metodo associato allevento passandogli levent object associato allevento
Listeners – (alcuni) metodi ActionListenervoid actionPerformed(ActionEvent) WindowListener void windowActivated(WindowEvent) void windowClosed(WindowEvent) ListSelectionListenervoid valueChanged(ListSelectionEvent) KeyListener void keyPressed(KeyEvent) void keyReleased(KeyEvent) void keyTyped(KeyEvent) MouseMotionListener void mouseMoved(MouseMotionEvent) void mouseDrag(MouseMotionEvent MouseListenervoid MouseClicked(MouseEvent) void mouseEntered(MouseEvent)
Listeners e Adapters Listeners : interfacce Adapters: classi (astratte) che implementano i listeners fornendo implementazioni default per i metodi dichiarati dai listeners La nomenclatura aiuta: XEvent : la classe associata allevento X XListener : linterfaccia che i listenerers dellevento X devono implementare XAdapter : la classe astratta che implementa XListener con metodi default:
: EventListener MouseMotionListener WindowListenerKeyListener ListSelectionListener MouseListenerActionListener Listeners
: EventListener MouseMotionListener WindowListenerKeyListener ListSelectionListener MouseListenerActionListener KeyAdapterMouseAdapterWindowAdapter Listeners e Adapters
Definizione di Listeners Implementiamo il Listener Estendiamo lAdapter class MyXAdapter extends XAdapter { // sovrascrive (alcuni de) i metodi definiti da XAdapter } class MyXListener implements XListener { // metodi definiti da XListener }
Registrazione di Listeners Ogni event source ha un metodo per registrare un corrispondente listener public void addXListener(XListener listener)
Esempio: ClickCounter 4 clickReset
Esempio: ClickCounter Gestione eventi: prima alternativa Il frame gestisce entrambi i pulsanti JFrame ClickCounter ActionListener
Esempio: ClickCounter JFrame ClickCounter ActionListener public class ClickCount extends JFrame implements ActionListener { int count = 0; JLabel clicks = new JLabel ("Total clicks = 0"); JButton b = new JButton ("click"); JButton r = new JButton ("reset");... public ClickCount() {... b.addActionListener(this); r.addActionListener(this); }... public void actionPerformed( ActionEvent e ) { if (e.getSource() == b) count++; else if (e.getSource() == r) count = 0; clicks.setText("Total clicks = " + count); }
Esempio: ClickCounter Gestione eventi: seconda alternativa I pulsanti gestiscono gli eventi autonomamente JFrame ClickCounter ActionListener 2
Esempio: ClickCounter public class ClickCount extends JFrame {... public ClickCount() {... b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { count++; clicks.setText("Total clicks = " + count); }}); r.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { count = 0; clicks.setText("Total clicks = " + count); }}); }... }
Domande Come disponiamo due pulsanti allineati sul lato inferiore di un frame? Come disponiamo tre pulsanti uno sopra laltro?
Risposte Prima le aggiungiamo ad un pannello (con FlowLayout ) e poi aggiungiamo il pannello allare sud del frame. Li disponiamo dentro un panello con GridLayout contenente tre righe ed una colonna
Esempio – EventFrame Una finestra che cattura e traccia un insieme di eventi del mouse
EventFrame – costruttore import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; /** EventFrame: traccia eventi di vario genere **/ class EventFrame extends JFrame { /** * Costruisce il Frame principale con le varie componenti */ public EventFrame() {
EventFrame – costruttore // Labels e TextFields per tracciare gli eventi JPanel eventFields = new JPanel(new BorderLayout()); Panel labels = new JPanel(new GridLayout(events.length,1)); JPanel traces = new JPanel(new GridLayout(events.length,1)); for (int i = 0; i < events.length; i++) { labels.add(events[i].label); traces.add(events[i].trace); } eventFields.add(labels,BorderLayout.WEST); eventFields.add(traces,BorderLayout.CENTER);
EventFrame – costruttore // Pulsanti JPanel buttons = new JPanel(new GridLayout(2,1)); buttons.add(new EventButton(Color.blue)); buttons.add(new EventButton(Color.red)); // Completa il layout setLayout(new GridLayout(1,2)); add(eventFields); add(buttons); }
Progetto dei Listeners : EventTracer MouseMotionListenerMouseListener Actiontracer ActionListener MouseTracerMouseMotionTracer
Classi interne – EventTracer private class EventTracer { /** * Costruisce il messaggio da visualizzare in risposta a * ciascun evento (sul campo testo corrispondente) * Overloade sul tipo dell'evento */ public void trace(int field, ActionEvent e) { // messaggio = numero di action events fino ad ora actionEvents++; displayMessage(field, "Event n. " + actionEvents); }
Classi interne – EventTracer public void trace(int field, MouseEvent e ) { // messaggio = numero di click consecutivi int mod = e.getModifiers(); String btn = "none"; if ( mod == 16 ) btn = "left"; else if (mod == 8 ) btn = "center"; else if (mod == 4 ) btn = "right"; displayMessage(field, btn + // + e.getX() + "," + e.getY() +")" + ", Clicks = " + e.getClickCount()); }
Classi interne – Listeners class ActionTracer extends EventTracer implements ActionListener { public void actionPerformed(ActionEvent e) { trace(ACTION, e); } ActionTracer(Color col) { super(col); } }
Classi interne – Listeners class MouseTracer extends EventTracer implements MouseListener { public void mouseClicked(MouseEvent e) { trace(MOUSE_CLICKED, e); } public void mouseEntered(MouseEvent e) { trace(MOUSE_ENTERED, e); } public void mouseExited(MouseEvent e) { trace(MOUSE_EXITED, e); } public void mousePressed(MouseEvent e) { trace(MOUSE_PRESSED, e); } public void mouseReleased(MouseEvent e) { trace(MOUSE_RELEASED, e); } MouseTracer(Color col) { super(col); } }
Classi interne – Listeners class MouseMotionTracer extends EventTracer implements MouseMotionListener { public void mouseDragged(MouseEvent e) { trace(MOUSE_DRAGGED, e); } public void mouseMoved(MouseEvent e) { trace(MOUSE_MOVED, e); } MouseMotionTracer(Color col) { super(col); } }
Classi interne – Pulsanti /** * Aree di tracciamento, definite come pulsanti * Registrano listeners per tutti gli eventi da tracciare */ class EventButton extends JButton { EventButton(Color c) { setBackground(c); addActionListener( new ActionTracer(c) ); addMouseListener( new MouseTracer(c) ); addMouseMotionListener( new MouseMotionTracer(c) ); } } // Conclude EventFrame
Esempio – Puzzle Forniamo una interfaccia grafica per il Puzzle che realizza il gioco del 15
Ricordiamo – PuzzleBoard Nella costruzione dellapplicazione, la classe PuzzleBoard funge da back-end L interfaccia grafica si limita in sostanza a fornire metodi di interazioni con il back-end
PuzzleBoard public class PuzzleBoard { /** costruisce una tabella con dimensione size */ public PuzzleBoard(int size) {... } /** il valore contenuto nella posizione (x,y) * -1 se la posizione è vuota */ public int val(int x, int y) {... } /** muove il pezzo che porta il numero w se questo * è in posizione adiacente alla posizione vuota */ public boolean move(int w) {... } /** true se la configurazione corrente è di successo */ public boolean win() {... } }
PuzzleFrame – struttura import java.awt.*; import java.awt.event.*; import javax.swing.*; class PuzzleFrame extends JFrame { // back-end private PuzzleBoard board; // dimensione del puzzle private int size; // i pezzi sull'interfaccia. Ciascun PuzzleButton è // associato alla corrispondente posizione sul backend private PuzzleButton[][] button;
PuzzleFrame – costruttore /** costruisce la tabella grafica a partire dalla * tabella b che costituisce il back-end */ public PuzzleFrame(int board_size, PuzzleBoard b) { size = board_size; board = b; button = new PuzzleButton[size][size]; setLayout(new GridLayout(size, size)); // crea i pulsanti associati ai pezzi e disponi for ( int i = 0; i != size; i = i+1 ) { for ( int j = 0; j != size; j = j+1 ) { button[i][j] = new PuzzleButton(); add(button[i][j]); } // inizializza pulsanti con i loro numeri display(); }
PuzzleFrame – refresh /** ridisegna la tabella dopo una mossa **/ private void display() { // ridisegna i numeri sui pulsanti for ( int i = 0; i != size; i = i+1 ) { for ( int j = 0; j != size; j = j+1 ) { if ( board.val(i,j) >= 0 ) { button[i][j].setBackground(Color.white); button[i][j].setText("" + board.val(i,j)); } else { button[i][j].setBackground(Color.black); button[i][j].setText( "" ); }
PuzzleFrame – refresh if (board.win()) { int response = JOptionPane.showConfirmDialog(this, "Done! Play again?"); switch (response) { case JOptionPane.YES_OPTION : board = new PuzzleBoard(size); display(); break; case JOptionPane.CANCEL_OPTION : break; default: System.exit(0); } } // chiude il metodo display()
PuzzleFrame – gestione pulsanti /** classe interna: controllore dei pulsanti */ class PuzzleButton extends JButton implements ActionListener { public PuzzleButton( ){ // numero del pulsante deciso da display() super(""); addActionListener(this); } public void actionPerformed(ActionEvent evt) { // prendi il numero di questo pulsante String s = getText(); if ( !s.equals("") ) { // non è il pulsante vuoto boolean ok = board.move(Integer.parseInt(s)); if ( ok ) { display(); } }
Componenti Swing Molte … sicuramente troppe per questo corso Consultate le API