Fab996 ha scritto:
So che potevo organizzare meglio i bottoni utilizzando un ArrayList inoltre che dovevo utilizzare il Event Dispatch Thread, ma devo ancora studiarlo. Poi cosa altro posso migliorare?
No, non è tanto questione di ArrayList per i pulsanti.
Hai usato un listener che è "esterno" alla classe della calcolatrice. Quindi hai dovuto "aprire" l'accesso a molte (troppe) cose:
- campi
public (altrimenti dal listener non potresti testare i pulsanti)
- metodi
public mostrazero ecc... (che altrimenti non potresti invocare).
Ti sembra buono? La questione, in generale, è che la gestione (implementazione) del listener dovrebbe essere più vicina e "intima" possibile al punto in cui sono gestiti i componenti. Avere un listener
esterno ha senso per certi design o quando la interazione è minima (es. si può fare tutto con il solo "source" dell'evento o poco più).
Inoltre, come dicevo prima, un aspetto importante è quello di saper "intravedere" cosa c'è di uguale e di diverso.
Tra:
public void mostrazero() {
etichetta.setText(this.cont+"0");
this.cont = this.cont+"0";
this.accumulatore = Integer.parseInt(this.cont);
}
e
public void mostrauno() {
etichetta.setText(this.cont+"1");
this.cont = this.cont+"1";
this.accumulatore = Integer.parseInt(this.cont);
}
e gli altri mostraXXX, cosa c'è di diverso e di uguale? Puoi generalizzare magari con un parametro? (certo che si può!)
Inoltre tieni presente che i pulsanti hanno un "actionCommand" che è una stringa arbitraria (e non c'entra niente con il testo
sul pulsante) ad uso del programmatore per farne un identificatore o una informazione. Nel caso di una calcolatrice può essere utile.
Mh, però non capisco perchè devo fare ActionListener asc = new Event(this), non dovrebbe essere Event asc = new Event(this)? O è presente qualche fenomeno di polimorfismo che trascuro?
Stessa cosa di prima. Ma è meglio che fissi bene il concetto, perché è così importante che se ti trascini dietro questi dubbi a lungo, non vai molto lontano ....
La "ereditarietà" definisce una relazione di generalizzazione/specializzazione tra due classi (tipi in generale). E porta al polimorfismo, cioè al concetto basilare che un tipo può essere visto
anche come uno dei tipi da cui deriva.
class Animale { }
class Gatto extends Animale { }
class GattoPersiano extends Gatto { }
Un oggetto GattoPersiano
è-un (in inglese la relazione si dice "IS-A") Gatto che
è-un Animale. Quindi un GattoPersiano può essere visto anche come Gatto e anche come Animale, allo stesso tempo.
E OVUNQUE sia richiesto un oggetto di tipo es. Animale, tu puoi lecitamente passare sia un oggetto Gatto, sia un GattoPersiano.
Se hai un metodo
public static void provaAnimale(Animale a)
tutti questi scenari sono validi:
GattoPersiano gp = new GattoPersiano();
provaAnimale(gp);
oppure
Gatto g = new GattoPersiano();
provaAnimale(g);
oppure
Animale a = new GattoPersiano();
provaAnimale(a);
Cosa cambia? Ai fini di provaAnimale nulla. Il metodo "sa" solo che è un Animale. Quello che in generale conta e può fare la differenza è la "visibilità" dei metodi/campi, che dipende SOLO dal tipo "statico" del reference (in questo caso la variabile definita e il parametro).
Se Gatto (e quindi anche GattoPersiano) ha un metodo miagola() ma Animale NON ce l'ha (ovviamente), il seguente NON funziona.
Animale a = new GattoPersiano();
a.miagola(); // NO
Anche se io so che GattoPersiano ha il miagola(), il compilatore NON può vederlo né invocarlo su una variabile di tipo Animale (anche se ci assegno un GattoPersiano!). Sono le regole di Java, che è un linguaggio "tipizzato staticamente".
Il compilatore si basa solo sul tipo "statico" del reference utilizzato nel codice per determinare cosa può accedere ed invocare.
Nel tuo caso siccome Event NON ha metodi in più e l'unico metodo actionPerformed viene invocato polimorficamente dal framework vedendo l'oggetto solo come ActionListener, che tu abbia nel tuo sorgente:
ActionListener asc = new Event(this);
xyz.addActionListener(asc);
oppure
Event ev = new Event(this);
xyz.addActionListener(ev);
Non fa differenza, non per addActionListener: si aspetta un ActionListener e Event
è-un ActionListener.
Se tu nel tuo Event avessi un metodo specifico per estrarre o settare informazioni, allora solo il secondo scenario ti sarebbe utile per invocarlo (variabile Event), altrimenti con ActionListener non potresti vederlo.