Cyrano ha scritto:
Tramite un Keyevent scelgo se creare un quadrato o un ovale.Ad esempio premento [O] per ovale e la lettera [Q] per quadrato.
Il problema e che quando devo inserire l'oggetto nella lista , devo comunque fare un IF per decidere se inserire un oggetto Quadrato o Ovale.
Questo è un punto in cui effettivamente una catena di if-else "sembrerebbe" necessaria. Da un certo punto di vista qui, in questo punto, non sarebbe un grosso problema avere gli if-else se: a) hai pochi elementi (3, 4 ... 7, 8 ), insomma, relativamente pochi elementi e b) la costruzione degli oggetti differisce abbastanza (un rettangolo avrà x/y/w/h mentre un cerchio avrà es. x/y/raggio o diametro, ecc...).
Questa scelta tra l'altro la fai una-tantum, solo quando l'utente sceglie una figura. Quindi NON ci sono problemi di performance particolari.
Quello che è importante è che poi in seguito, quando dovrai ripetutamente disegnare gli elementi, NON andrai più a fare una catena di if-else ma sfrutterai il polimorfismo come già detto in precedenza. Qui, è importante evitare menate poco OOP.
E comunque, se proprio si volesse, si potrebbe generalizzare anche la scelta/creazione degli oggetti specifici. Semplicemente mettendo a frutto di nuovo la ereditarietà/polimorfismo. Ma bisogna valutare COSA astrarre. Come ho detto, per costruire gli oggetti potrebbero essere necessari dati differenti (vedi il caso rettangolo vs cerchio). Possiamo generalizzarlo? Ad esempio stabilire che per creare una figura si deve specificare un rettangolo di "bounding box" (in cui la figura è inscritta) e ad esempio un colore.
Possiamo definire una interfaccia che descrive una "factory" per costruire oggetti di un certo tipo:
public interface FiguraDisegnabileFactory<T extends FiguraDisegnabile> {
T creaFigura(Rectangle rect, Color color);
}
(Rectangle/Color sono ora per comodità quelli di java.awt)
Poi nella applicazione tieni una mappa di stringhe associate alle factory.
Map<String,FiguraDisegnabileFactory<? extends FiguraDisegnabile>> mappaFactory = new HashMap<>();
Poi puoi popolare questa mappa "una-tantum" ovvero solo UNA volta (magari all'inizio della applicazione). Lo puoi fare con una anonymous inner-class.
mappaFactory.put("R", new FiguraDisegnabileFactory<Rettangolo>() {
@Override
public Rettangolo creaFigura(Rectangle rect, Color color) {
return new Rettangolo(rect.x, rect.y, rect.width, rect.height, color);
}
});
Oppure in Java 8 con una lambda expression:
mappaFactory.put("R", (rect,color) -> new Rettangolo(rect.x, rect.y, rect.width, rect.height, color));
Quando nell'evento avrai un codice stringa es. "R", potrai fare un lookup (ricerca) nella mappa.
String codice = //...scelto dall'utente
FiguraDisegnabileFactory<? extends FiguraDisegnabile> factory = mappaFactory.get(codice);
FiguraDisegnabile figura = factory.creaFigura(unRettangolo, unColore);
Questo di fatto SOSTITUISCE una catena di if-else !! Chiaramente unRettangolo/unColore li dovrai costruire o comunque avere in qualche modo prima di creare la figura.
Ovviamente c'è ben più codice da scrivere ma è molto lineare e sicuramente più "object-oriented" rispetto ad una catena di if-else. Specialmente se avessi 20, 30, ecc.. tipi di figure.
Il fatto di avere un'altra gerarchia (FiguraDisegnabileFactory e N implementazioni) è servito per uno scopo: "
appiattire" le differenze nella costruzione delle varie figure. A questo infatti serve spesso la ereditarietà/polimorfismo.
Così come FiguraDisegnabile serve per "appiattire" le differenze nei confronti del disegno delle figure.
Cyrano ha scritto:
Non ho un riferimento 'vuoto' al quale inserire l'indirizzo dell'oggetto ovale o quadrato a seconda della scelta con keyevent.
Non posso nemmeno passare l'oggetto ad una funzione incaricata di inserirlo nella lista , perchè gli oggetti sono di diverso tipo.
Ovvero non so se c'e un ref o un contenitore per ospitare oggetti differenti.( mi viene da dire puntatore , ma probabilmente sbaglio anche perchè non esistono in java)
Forse mi sono spiegato male
Forse stai cercando di fare cose "avanzate" ma senza avere ancora chiare le basi sulla OOP.
Se ho una variabile di tipo FiguraDisegnabile (la interfaccia di cui ho già parlato):
FiguraDisegnabile figura;
a questa variabile posso assegnare il riferimento a un QUALUNQUE oggetto che implementa questa interfaccia. Se Rettangolo, Cerchio, Ovale ecc.. la implementano, posso fare:
figura = new Rettangolo( ..... );
poi dopo
figura = new Cerchio( ...... );
ecc...
E in maniera similare, se ho un List<FiguraDisegnabile> ciascun elemento può essere un QUALUNQUE oggetto che implementa FiguraDisegnabile.
Questo, ripeto, è il "polimorfismo", derivante dalla ereditarietà.