PDA

View Full Version : [java] override metodi


*MATRIX*
27-03-2009, 17:45
ciao raga non sono molto pratico di java

mi potete dire se questo override è legale?

http://g.imagehost.org/0671/Class_Model.jpg (http://g.imagehost.org/download/0671/Class_Model)

PGI-Bis
27-03-2009, 18:31
Non c'è sovrascrittura di metodi in quel diagramma. C'è invece sovraccaricamento (metodo con lo stesso nome ma lista di parametri diversa).

*MATRIX*
27-03-2009, 18:34
Non c'è sovrascrittura di metodi in quel diagramma. C'è invece sovraccaricamento (metodo con lo stesso nome ma lista di parametri diversa).

Come posso fare allora per definire il metodo press per ogni sottoclasse?

yorkeiser
27-03-2009, 19:04
Per override si intende definire un metodo con la stessa signature (ovvero nome e parametri in ingresso) della classe madre.
Quindi ti basta definire nelle classi figlie lo stesso IDENTICO metodo (in termini di signature ovviamente, il corpo sarà diverso, altrimenti non avrebbe senso ridefinirli) della classe madre, ovvero press()

PGI-Bis
27-03-2009, 21:39
Come posso fare allora per definire il metodo press per ogni sottoclasse?

Dipende da "quello che vuoi fare". Se vuoi invocare "il metodo giusto in base al tipo di argomento" allora la faccenda è interessante. Bisogna infatti tener conto che, in Java:

class A {
void metodo(Object arg) {
System.out.println("object");
}
}

class B {
void metodo(String arg) {
System.out.println("string");
}
}

A a = new B();
a.metodo("hello world");

Stampa "object" e non "string".

Ciò avviene perchè la risoluzione del nome del metodo da invocare è determinata a tempo di compilazione in base ai metodi disponibili nel tipo in compilazione. A.metodo(una stringa) diventa il metodo(Object) dichiarato in A (ed esteso in B) perchè A non dichiara un metodo(String).

Una soluzione è:

class Bottoni {
void press(Object arg) {}
void press(char c) {}
void press(int i) {}
void press(String s) {}
}

class BottoniAlfabetici {
void press(char c) {}
}

class BottoniNumerici {
void press(int i) {}
}

class BottoniOperazioni {
void press(String s) {}
}

Qui hai sovrascrittura.

Bottoni x = new BottoniAlfabetici();
x.press(10); //-> invoca la definizione di press(int) data in BottoniAlfabetici

Esistono alternative più esotiche, ad esempio una mappa di funtori, o esoteriche, vale a dire l'invocazione riflessiva di metodi.

La prima cambia il design della tua gerarchia di tipi, la seconda non è neppure esprimibile in un diagramma di classi UML riferito a Java :D.

TorpedoBlu
03-04-2009, 11:36
meglio lavorare con un interfaccia implementata da una classe delegate che si preoccupa di istanziare la classe giusta / il metodo giusto attraverso il pattern factory.

(se poi dovrai modificare qualcosa o aggiungere nuove implementazioni del metodo non dovrai modificare l'interfaccia, ma solo aggiungere una nuova classe e modificare il factory, disaccoppiando il resto dalle tue classi)

PGI-Bis
03-04-2009, 15:32
E come risolvi il problema dell'invocazione dinamica di un metodo sovraccaricato?

TorpedoBlu
03-04-2009, 16:55
E come risolvi il problema dell'invocazione dinamica di un metodo sovraccaricato?

la chiamata è wrappata apposta per non essere più il compilatore a scegliere.

cmq nel disegno il problema è che il metodo deve avere la stessa segnatura.

al massimo wrappi il parametro in ingresso

PGI-Bis
03-04-2009, 17:32
In pratica ad un certo punto sei costretto ad una conversione esplicita.

Rinunciare al typesystem non è una buona idea. Tanto varrebbe usare uno script e rischiare di spararsi nei piedi ogni due enunciati.

Non che l'interfaccia sia una brutta idea, anzi. Bottone grida "interfaccia" in ogni direzione. Le factory poi in Java sono come la manna: risolvono il problema dei costruttori che non restituiscono istanze.

Qui il problema però è che A.press(T) è supposto covariante in B.press(V) per ogni B <: A e T <: V.

Mentre in Java è invariante.

Tra l'altro forse il problema è questo. Non ho ancora saputo se l'intenzione implicita è poter dire:

Bottone x = new BottoneNumerico();
x.press(10);

e non ottenere un lamento dal compilatore o se il problema sia un altro.