interfacce e polimorfismo - università ca' foscari veneziapo/slides/04interfaces.pdf ·...
TRANSCRIPT
![Page 1: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/1.jpg)
Interfacce e Polimorfismo
![Page 2: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/2.jpg)
Interfacce
• Dichiarazioni di tipi riferimento che descrivono oggetti in modo astratto
• Specificano solo le firme dei metodi tralasciando tutti gli aspetti di implementazione
![Page 3: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/3.jpg)
Interfacce
interface Poly { public Poly somma (Poly p);
public Poly derivata();
public int grado();
public boolean equals (Poly p);
public double coefficient(int degree);
}
![Page 4: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/4.jpg)
Interfacce
interface Collection<E> { public void add(E element);
public void remove(E element);
public boolean find(E element);
. . .
}
![Page 5: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/5.jpg)
Classi implementano Interfacce
• La keyword implements indica che una classe implementa una interfaccia
class TreeSet<E> implements Collection<E>
{ ... }
class ArrayPoly implements Poly{ ... }
![Page 6: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/6.jpg)
Classi implementano Interfacce
• Una classe che implementa una interfaccia deve implementare tutti i metodi dell’interfaccia
• Tutti I metodi dell’interfaccia devono essere dichiarati public nella classe
• Nulla vieta che la classe dichiari altri metodi oltre quelli dell’interfaccia che implementa
![Page 7: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/7.jpg)
Classi implementano Interfacce• Una interfaccia può essere implementata da più
classi
class ListPoly implements Poly
{ ... }
class ArrayPoly implements Poly { ... }
![Page 8: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/8.jpg)
Classi implementano Interfacce• Una interfaccia può essere implementata da più
classi
class TreeSet<E> implements Collection<E>
{ ... }
class HashMap<E> implements Collection<E>{ ... }
![Page 9: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/9.jpg)
Conversioni di tipo
• Una interfaccia “rappresenta” tutte le classi che la implementano
• Il tipo interfaccia si può associare a tutti gli oggetti delle classi che la implementano
Continua…
![Page 10: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/10.jpg)
Conversioni di tipo
• Possiamo assegnare un riferimento di tipo classe ad una variabile di tipo interfaccia purchè la classe implementi l’interfaccia
Collection<Double> c = new TreeSet<Double>();
Collection<Double> d = new HashMap<Double>();
Poly p = new ArrayPoly();
Poly q = new ListPoly();
Continua…
![Page 11: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/11.jpg)
Conversioni di tipo
• La conversione è lecita solo in determinate situazioni
• Problema: TreeSet<Double>() non implementa Poly
Poly x = new TreeSet<Double>(); // ERRORE
![Page 12: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/12.jpg)
Conversioni di Tipo
• Sottotipo (<:)– La relazione che permette di decidere quando è lecito
convertire un tipo riferimento in un altro – Per il momento diciamo
• Principio di sostituibilità– Ovunque ci si aspetti un riferimento di un tipo è lecito
utilizzare un rifetimento di un sottotipo
Continua…
S <: T sse ● S è una classe, T è una interfaccia ● S implementa T.
![Page 13: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/13.jpg)
Conversioni di Tipo
• Assumiamo S <: T
• Regola di assegnamento– Un riferimento di tipo S si puo sempre assegnare ad una variabile
di tipo T – Un riferimento di tipo classe può sempre essere assegnato ad
una variabile di tipo interfaccia che la classe implementa
• Regola di passaggio di parametri– Un riferimento di tipo S si puo sempre passare per un parametro
di tipo T– Un riferimento di tipo classe può sempre essere passato per un
parametro di tipo interfaccia che la classe implementa
![Page 14: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/14.jpg)
Conversioni di Tipo
• Le conversioni abilitate dalla regola
C <: I sse C implementa I
sono “corrette” – garantiscono che le proprietà che valgono
utilizzando valori di tipo I valgono usando valori di tipo C
• Dimostrazione intuitiva: – Se C implementa I , C deve definire tutti i metodi
dichiarati da I (e dichiararli public)– Quindi tutti le invocazioni di metodo ammesse da I
trovano effettivamente un metodo definito in C Continua…
![Page 15: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/15.jpg)
Polimorfismo – dynamic dispatch
• Le regole di conversione di tipo garantiscono che una variabile di tipo interfaccia ha sempre come valore un riferimento di una classe che implementa l’interfaccia
• Se una interfaccia è implementata da più classi, il tipo dei valori legati alla variabile può cambiare
Continua…
Poly p;p = new ListPoly(...);p = new ArrayPoly(...);
![Page 16: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/16.jpg)
Polimorfismo – dynamic dispatch
• Possiamo invocare ognuno dei metodi dell’interfaccia:
• Quale metodo invoca?
int g = p.grado();
![Page 17: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/17.jpg)
Polimorfismo – dynamic dispatch
• Se p riferisce un ListPoly, invoca il metodo ListPoly.grado()
• Se p riferisce un ArrayPoly, invoca il metodo ArrayPoly.grado();
• Polimorfismo (molte forme): – il metodo invocato dipende dipende dal tipo del
riferimento legato alla variabile
Continua…
int g = p.grado();
![Page 18: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/18.jpg)
• Costruiamo una applicazione per disegnare un insieme di forme geometriche contenute in una componente grafico:– definiamo GWin, una classe che descrive un
contenitore di forme geometriche disegnate mediante una invocazione del metodo paint()
– per esemplificare, consideriamo due tipi di forme: Quadrato e Cerchio
Esempio
![Page 19: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/19.jpg)
Forme grafiche
class Quadrato{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }} class Cerchio
{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }}
![Page 20: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/20.jpg)
• Un contenitore di Quadrati e Cerchi
GWin
/** Una finestra che contiene Quadrati e Cerchi */ class GWin { /** Disegna tutte le forme di questo component */ public void paint(){ /* disegna su g */ } /**
Componente grafica su cui disegnare */ private Graphics2D g; }
![Page 21: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/21.jpg)
Domanda
• Che struttura utilizziamo per memorizzare le forme contenute nella GWin?
• Come definiamo il metodo paint() in modo che disegni tutte le forme della componente?
![Page 22: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/22.jpg)
Risposte
• definiamo una nuova interfaccia: Shape
• Ridefiniamo le classi Quadrato e Cerchio in modo che implementino Shape
• Memorizziamo gli oggetti della componente in una ArrayList<Shape>
interface Shape { void draw(Graphics2D g); }
![Page 23: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/23.jpg)
Shapes
class Quadrato implements Shape
{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }}
class Cerchio implements Shape
{ . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . }}
![Page 24: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/24.jpg)
Mantiene una ArrayList<Shape>
GWin
class GWin { private Graphics2D g; private ArrayList<Shape> shapes; // crea una GWin con un insieme di forme public GWin(Shape... shapes) { Graphics2D g = new Graphics2D();
this.shapes = new ArrayList<Shape>(); for (Shape s:shapes) this.shapes.add(s); } // disegna tutte le componenti della GWin public void paint() {
for (Shape s:shapes) s.draw(g); } }
![Page 25: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/25.jpg)
Diagramma delle Classi
Car
GWin
Cerchio
Shape
Quadrato
![Page 26: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/26.jpg)
Ancora Interfacce
![Page 27: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/27.jpg)
Esempio
• Definiamo una classe DataSet che permette di condurre alcune semplici analisi su un insieme di conti bancari
– calcolo della media degli importi del saldo– calcolo del conto con il valore massimo tra i saldi
Continua…
![Page 28: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/28.jpg)
DataSetpublic class DataSet { public void add(BankAccount x) { if (x == null) return; 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 29: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/29.jpg)
Esempio – Data Analysis
• Ora ripetiamo l’esempio per definire una versione della classe DataSet che permette di condurre alcune semplici analisi su un insieme di corsi universitari:
– calcolo della media del numero di studenti per corso– calcolo del corso con massimo numero di studenti
class Corso{ // . . . public double iscritti() { // ... }}
![Page 30: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/30.jpg)
DataSet – versione per Corsopublic class DataSet { public void add(Corso x) { if (x == null) return; sum = sum + x.iscritti(); if (count == 0 || maximum.iscritti() < x.iscritti()) maximum = x; count++; }
public Corso getMaximum() { return maximum; } public double average() {return (count>0)? sum/count : Double.NaN; } private double sum; private Corso maximum; private int count; }
![Page 31: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/31.jpg)
Interfacce riuso di codice
• Il meccanismo di analisi dei dati è sempre lo stesso; – si basa sull’estrazione di una misura – la differenza è solo nell’implementazione del metodo che
fornisce la misura
• Possiamo uniformare: – è sufficiente stabilire una modalità uniforme per estrarre la
misura.
interface Measurable { double getMeasure(); }
![Page 32: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/32.jpg)
Measurable BankAccounts
public class BankAccount implements Measurable { public double getMeasure() { return getBalance(); } // ... }
Continua…
![Page 33: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/33.jpg)
Measurable Corsi
class Corso implements Measurable { public double getMeasure() { return iscritti(); } // . . . }
![Page 34: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/34.jpg)
DataSet – versione generica
public class DataSet{ public void add(Measurable x) {
if (x == null) return; 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 35: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/35.jpg)
DataSet Diagramma UML
dipende
implementa
Corso
![Page 36: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/36.jpg)
Interfacce multiple
• Una classe può implementare più di una interfaccia
• In quel caso deve definire, public, tutti i metodi delle interfacce che implementa
• E’ automaticamente sottotipo di ciascuna delle interfacce che implementa
![Page 37: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/37.jpg)
Measurable Shapes
class Quadrato implements Shape, Measurable
{ . . . public void draw(Graphics2D g) { ... } public double getMeasure() { ... } }
class Cerchio implements Shape, Measurable
{ . . . public void draw(Graphics2D g){ ... } public void getMeasure() { ... }}
![Page 38: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/38.jpg)
Measurable Shapes
• Ora possiamo passare Quadrati e Cerchi sia all’interno della classe Gwin per essere disegnati, sia all’interno della classe DataSet per essere misurati
![Page 39: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/39.jpg)
Conversioni di tipo
• Una interfaccia “rappresenta” tutte le classi che la implementano
• Più in generale: un supertipo rappresenta tutti i suoi sottotipi
Continua…
![Page 40: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/40.jpg)
Conversioni di tipo
• Principio di sostituibilità– Un riferimento di un sottotipo può essere usato
ovunque ci si aspetti un riferimento di un supertipo
• Può causare perdita di informazione– nel contesto in cui ci aspettiamo il supertipo, non
possiamo usare solo I metodi del supertipo– perdiamo la possibilità di utilizzare gli eventuali metodi
aggiuntivi del sottotipo
Continua…
![Page 41: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/41.jpg)
Ancora Shapes
class Smiley implements Shape
{ . . .public void draw(Graphics2D g){ . . . }public String mood() {. . . }
}
class Car implements Shape
{ . . .public void draw(Graphics2D g){ . . . }public String brand() {. . . }
}
![Page 42: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/42.jpg)
Sottotipi e perdita di informazione
• Consideriamo
public static void printBrand(List<Shape> l)
{ for (Shape s : l)
// stampa la marca di tutte le macchine di l
System.out.println(s.brand());
Continua…
![Page 43: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/43.jpg)
Sottotipi e perdita di informazione
• Certamente non possiamo fare così …
public static void printBrand(List<Shape> l)
{ for (Shape s : l)
// stampa la marca di tutte le macchine di l
System.out.println( s.brand() ); // TYPE ERROR!
}
Continua…
![Page 44: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/44.jpg)
Cast
• Permette di modificare il tipo associato ad una espressione
• 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 s non è un Car errore a run time
Continua…
((Car)s).brand()
![Page 45: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/45.jpg)
Tipo statico e Dinamico
• Tipo statico e tipo dinamico di una variabile– tipo statico: quello dichiarato – tipo dinamico: il tipo del riferimento assegnato alla
variabile
• Il tipo dinamico può cambiare durante l’esecuzione, ma le regole garantiscono che
– Il tipo dinamico di una variabile è sempre un sottotipo del tipo statico della variabile
Continua…
![Page 46: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/46.jpg)
Cast
• (T)var causa errore – in compilazione
se T non è compatibile con il tipo statico di var– in esecuzione (ClassCastException)
se T non è compatibile con il tipo dinamico di var
Continua…
![Page 47: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/47.jpg)
Cast
• OK: Car sottotipo di Shape
• Compila correttamente – il tipo dichiarato di s è Shape – Car e Shape sono compatibili
• Esegue correttamente – s è un Car (il tipo dinamico di s è Car)
Shape s = new Car();
Continua…
Car c = (Car) s
![Page 48: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/48.jpg)
Cast
• OK: Car sottotipo di Shape
• Compila correttamente – il tipo dichiarato di s è Shape – Smiley e Shape sono compatibili
• Errore a run time – s non è uno Smiley
Shape s = new Car();
Continua…
Smiley c = (Smiley) s
![Page 49: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/49.jpg)
Cast
• Attenzione anche qui …
public static void printBrand(List<Shape> l)
{ for (Shape s : l)
// ClassCastException se s instance of Smiley
System.out.println( ((Car)s).brand() );
}
Continua…
![Page 50: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/50.jpg)
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 51: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/51.jpg)
Cast
• Questo, finalmente, è corretto
public static void printBrand(List<Shape> l)
{ for (Shape s : l)
if (s instanceof Car)
System.out.println( ((Car)s).brand() );
}
![Page 52: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/52.jpg)
Domanda
• Come disegnare solo le Shapes che sono Cars?
![Page 53: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/53.jpg)
Risposta
// disegna tutte le Cars della GWin
public void paint(){ for (Shape c:shapes)
if (c instanceof Car) c.draw(g); }
![Page 54: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/54.jpg)
Polinomi
• Polinomi (http://www.dais.unive.it/~po/Labs/interfaces.html)
interface Poly { public Poly somma (Poly p);
public Poly derivata();
public int grado();
public boolean equals (Object q)
public boolean equals (Poly p);
public double coefficient(int degree);
}
![Page 55: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/55.jpg)
Polinomi – equals()
• Notiamo le due versioni – entrambi sono necessarie – Dimostrano un aspetto interessante dell’interazione
tra il meccanismi di polimorfismo (dynamic dispatch) e di risoluzione dell’overloading
![Page 56: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/56.jpg)
Dynamic dispatch vs overloading
• Dynamic dispatch:– Il metodo da invocare per rispondere ad un
messaggio è deciso a tempo di esecuzione
• Notiamo bene– Il metodo da invocare è deciso a runtime– il compilatore decide se esiste un metodo da
invocare
• Overloading: – Nel caso esista più di un metodo, il compilatore
decide staticamente il tipo del metodo da invocare
![Page 57: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/57.jpg)
Dynamic dispatch vs overloading
interface I { public String m(boolean b); public String m(double d); } class A implements I { public String m(boolean b) { return “A.m(boolean)”; } public String m(double d) { return “A.m(double)”; } }
class B implements I { public String m(boolean b) { return “B.m(boolean)”; } public String m(double d) { return “B.m(double)”; } }
![Page 58: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/58.jpg)
Polinomi – equals()
• Consideriamo:
• Data la dichiarazione q:Object la chiamata p.equals(q)viene associata alla firma Poly.equals(Object)
• eDinamincamente, poi, viene dispacciata al corpo del metodo ArrayPoly.equals(Object)
Poly p = new ArrayPoly(); Object q = new ListPoly(); p.equals(q);
![Page 59: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/59.jpg)
Interfacce standard – Listeners
• Le librerie Java forniscono molte interfacce standard, che possono essere utilizzare nella programmazione
• Un insieme interessante di queste interfacce è legata al framework Swing, ed utilizzata per la programmazione ad eventi, tipica delle applicazioni con interfaccia grafica
![Page 60: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/60.jpg)
Eventi, Sorgenti, e Listeners• Una interfaccia utente deve gestire una
moltitudine di eventi– eventi da tastiera, del mouse, click su pulsanti, …
• Opportuno poter discriminare diversi eventi– componenti specifiche devono poter essere
programmate senza preoccuparsi che di eventi specifici
• Necessario avere meccanismi per gestire eventi in modo selettivo
– Un meccanismo per dichiarare quali eventi si intendono gestire
Continua…
![Page 61: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/61.jpg)
• Listener: – Oggetto che viene notificato dell’occorrere di un
evento – I suoi metodi descrivono le azioni da eseguire in
risposta ad un evento
• Sorgente di eventi: – Oggetto che origina eventi, o li emette, – Notifica l’evento ai propri listeners
• Vari tipi di sorgenti– Componenti visuali: JButton, JTextField, ...– Timer, …
Eventi, Sorgenti, e Listeners
Continua…
![Page 62: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/62.jpg)
• Ogni sorgente genera un insieme ben definito di eventi
– determinato dal tipo della sorgente
• Eventi di basso livello– mouse-down/up/move, key-press/release,
component-resize/move, …
• Eventi “semantici”– ActionEvent: click su un JButton, doppio-
click su un JListItem, tick di un Timer– TextEvent: JTextField modificato da uno
o più mouse/key events
Eventi, Sorgenti, e Listeners
Continua…
![Page 63: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/63.jpg)
• Gestione mirata degli eventi– Una applicazione può decidere quali eventi gestire tra
quelli generati da ciascuna sorgente
• Registra su ciascuna componente solo i listeners degli eventi che intende gestire
Eventi, Sorgenti, e Listeners
Continua…
![Page 64: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/64.jpg)
Eventi, Sorgenti, e Listeners
• Esempio: utilizziamo una componente JButton per realizzare un pulsante: associamo a ciascun pulsante un ActionListener
• Ricordiamo:
• Dobbiamo fornire una classe il cui metodo actionPerformed contiene le istruzioni da eseguire quando il pulsante viene premuto
public interface ActionListener { void actionPerformed(ActionEvent event); }
Continua…
![Page 65: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/65.jpg)
Eventi, Sorgenti, e Listeners
• event contiene informazioni sull’evento (ad esempio l’istante in cui è avvenuto)
• Associamo il listener al pulsante, registrandolo sul pulsante:
• addActionListener(): un metodo di JButton
ActionListener listener = new ClickListener(); button.addActionListener(listener);
void addActionListener(ActionListener l);
![Page 66: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/66.jpg)
File ClickListener.java
01: import java.awt.event.ActionEvent;02: import java.awt.event.ActionListener;03: 04: /**05: Un action listener che stampa un messaggio06: */07: public class ClickListener implements ActionListener08: {09: public void actionPerformed(ActionEvent event)10: {11: System.out.println("I was clicked.");12: } 13: }
![Page 67: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/67.jpg)
File ClickApp.javaimport java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame; public class ClickApp{ public static void main(String[] args) { JFrame frame = new JFrame(); JButton button = new JButton("Click me!"); frame.add(button);
button.addActionListener(new ClickListener());frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static final int FRAME_WIDTH = 100; private static final int FRAME_HEIGHT = 60;}
![Page 68: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/68.jpg)
File ClickListener.java
Output:
![Page 69: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/69.jpg)
Eventi del mouse
• mousePressed, mouseReleased: invocati quando un pulsante del mouse viene premuto o rilasciato
• mouseClicked: invocato quando un pulsante del mouse viene cliccato
• mouseEntered, mouseExited: il mouse è entrato o è uscito dall’area della componente
![Page 70: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/70.jpg)
Eventi del mouse• Catturati da MouseListeners
Continua…
public interface MouseListener { // un metodo per ciascun mouse event su una componente
void mousePressed(MouseEvent event); void mouseReleased(MouseEvent event); void mouseClicked(MouseEvent event); void mouseEntered(MouseEvent event); void mouseExited(MouseEvent event); }
![Page 71: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/71.jpg)
Eventi del mouse
• Se vogliamo che una componente reagisca ad eventi del mouse dobbiamo registrare un MouseListener sulla componente:
Continua…
public class MyMouseListener implements MouseListener { // Implementa i cinque metodi} MouseListener listener = new MyMouseListener(); component.addMouseListener(listener);
![Page 72: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/72.jpg)
Mouse Events
class MousePressListener implements MouseListenere { public void mousePressed(MouseEvent event) { int x = event.getX(); int y = event.getY(); . . . }
// implementazione degli altri metodi dell’interfaccia}
• Tutti i metodi devono essere implementati; implementazione vuota se inutili
![Page 73: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/73.jpg)
ActionListener
• Descrive oggetti che svolgono il ruolo di gestori di eventi:
– rimane attesa (in ascolto) di un evento, per poi rispondere con una azione al momento in cui l’evento si manifesta
interface ActionListener{ void actionPerformed(ActionEvent event);}
![Page 74: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/74.jpg)
Eventi di un timer
• Eventi notificati ad un ActionListener associato al timer
• Il gestore viene attivato ad ogni tick del timer
– actionPerformed() invocato ad ogni tick– event: contiene informazione sull’evento
public interface ActionListener{ void actionPerformed(ActionEvent event);}
Continua…
![Page 75: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/75.jpg)
Eventi di un timer
• La gestione dell’evento avviene nel metodo actionPerformed()
• Gestioni diverse realizzate da classi diverse che implementano ActionListener
class TimerListener implements ActionListener{ public void actionPerformed(ActionEvent event) { // Eseguito ad ogni tick. }}
Continua…
![Page 76: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/76.jpg)
Eventi di un timer
• Per associare un particolare listener al timer è necessario registrare il listener sul timer
• Ora possiamo far partire il timer
TimerListener listener = new TimerListener();Timer t = new Timer(interval, listener);
t.start(); // Esegue in un thread separato
tra due tick
![Page 77: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/77.jpg)
Esempio: countdown
• Un timer che esegue il countdown
![Page 78: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/78.jpg)
CountDownListener
public class CountDownApp{ public static void main(String[] args) { CountDownListener listener = new CountDownListener(10); // Millisecondi tra due tick final int DELAY = 1000; Timer t = new Timer(DELAY, listener); t.start();
JOptionPane.showMessageDialog(null, "Quit?"); System.exit(0); }}
![Page 79: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/79.jpg)
CountDownListener
• Inizializza un contatore al valore passato nel costruttore
• Ad ogni invocazione del metodo actionPerformed()
– controlla il valore del contatore e dà in output il messaggio corrispondente
– decrementa il contatore
![Page 80: Interfacce e Polimorfismo - Università Ca' Foscari Veneziapo/Slides/04Interfaces.pdf · Polimorfismo – dynamic dispatch • Le regole di conversione di tipo garantiscono che una](https://reader035.vdocuments.site/reader035/viewer/2022062602/5edfa62cad6a402d666afab5/html5/thumbnails/80.jpg)
CountDownListener
class CountDownListener implements ActionListener{ public CountDownListener(int initialCount) {
count = initialCount; }
public void actionPerformed(ActionEvent event) {
if (count >= 0) System.out.println(count);if (count == 0) System.out.println("Liftoff!");count--;
} private int count;}