PDA

View Full Version : [Java] problema con la reflection nel caso di ereditarietà


dierre
19-01-2011, 18:00
Sto seguendo l'articolo di Oracle Techwork su come implementare l'mvc nel caso di desktop application ed ho un problema quando devo richiamare metodi del controller che hanno come argomento una superclasse.

http://www.oracle.com/technetwork/articles/javase/index-142890.html

Nel mio caso io ho come superclasse Directory e come sottoclassi SimpleDirectory e Wildcarded directory.

Il controller astratto ha questo metodo con cui richiama i metodi del modello:

protected void setModelProperty(String propertyName, Object newValue) {



for (AbstractModel model: registeredModels) {
try {

Method method = model.getClass().
getMethod(propertyName, new Class[] {
newValue.getClass()
}
);

method.invoke(model, newValue);

} catch (Exception ex) {
ex.printStackTrace();
}
}
}


Nel mio caso il metodo da richiamare è:


public void addDirectoryDummy(Directory d){
System.out.println("Hello!");
}


e nel controller reale ho:

public void dummy( Directory d){
setModelProperty( BACKUP_DUMMY, d );
}


nella vista richiamo il controller in questo modo:

this.controller.dummy( new SimpleDirectory(0,"ciao") );

Da cui ho la seguente eccezione


java.lang.NoSuchMethodException: it.univpm.quickbackup.models.BackupManager.addDirectoryDummy(it.univpm.quickbackup.models.SimpleDirectory)
at java.lang.Class.getMethod(Class.java:1605)


Dalla documentazione ho che getMethod

The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order.

Come posso risolvere il problema?

wingman87
19-01-2011, 20:05
In effetti leggendo la descrizione dell'algoritmo utilizzato pare che non abbiano tenuto conto di questo.
Non so se va bene per le tue esigenze ma potresti scrivere un metodo che faccia quello che ti serve. Dovresti utilizzare il metodo getMethods() di Class per ottenere tutti i metodi e poi tra questi cercare quello giusto confrontando i tipi dei parametri. I parametri li ottieni con il metodo getParameterTypes() di Method. Per fare i confronti useresti il metodo isAssignableFrom() di Class.

dierre
21-01-2011, 14:19
Grazie mille! Risolto!


public class Test
{
public static void main(String[] args) throws Exception {
Test test = new Test();
Child child = new Child();

// A working approach
for (Method method : test.getClass().getMethods()) {
if ("doSomething".equals(method.getName())) {
if (method.getParameterTypes()[0].isAssignableFrom(child.getClass())) {
method.invoke(test, child);
}
}
}
System.out.println("This works");

}

public void doSomething(Parent parent) {

}
}

class Parent {

}

class Child extends Parent {

}

banryu79
21-01-2011, 14:25
Grazie mille! Risolto!

Se hai 5 minuti potresti tornare alla pagina dell'articolo e inviare un feedback segnalando errore e correzione usando la funzione a fondo pagina di "Rate and Review" ;)

dierre
21-01-2011, 14:29
Se hai 5 minuti potresti tornare alla pagina dell'articolo e inviare un feedback segnalando errore e correzione usando la funzione a fondo pagina di "Rate and Review" ;)

Non è esattamente un errore, e la mia non è esattamente una soluzione in quanto manca la gestione del numero variabile di argomenti. Io al momento sto facendo un override per avere 1 o 0 argomenti da invocare col nome del metodo che è di una bruttezza unica.

banryu79
21-01-2011, 14:32
Non è esattamente un errore, e la mia non è esattamente una soluzione in quanto manca la gestione del numero variabile di argomenti. Io al momento sto facendo un override per avere 1 o 0 argomenti da invocare col nome del metodo che è di una bruttezza unica.
Sì hai ragione :doh:
Sono un po' a corto di sonno, e oggi ogni tanto svariono :D

dierre
21-01-2011, 14:39
Sì hai ragione :doh:
Sono un po' a corto di sonno, e oggi ogni tanto svariono :D

A chi lo dici, io ho un esame lunedì.