Questa linea sembra riassumere il nocciolo del problema:
Il problema con questo è che ora non è possibile chiamare tutti i nuovi metodi (solo override) sul implementazione della classe, poiché la variabile di riferimento dell'oggetto ha il tipo di interfaccia.
Sei abbastanza bloccato nella tua implementazione attuale, in quanto non solo devi provare un cast, hai anche bisogno della definizione dei metodi che vuoi chiamare in questa sottoclasse. Vedo due opzioni:
1. 1. Come specificato in precedenza, non è possibile utilizzare la rappresentazione String del nome della classe per trasmettere l'istanza riflessa a un tipo noto. È possibile, tuttavia, utilizzare un test String
equals()
per determinare se la classe è del tipo che si desidera, e quindi eseguire un cast hard-coded:
try {
String className = "com.path.to.ImplementationType";// really passed in from config
Class c = Class.forName(className);
InterfaceType interfaceType = (InterfaceType)c.newInstance();
if (className.equals("com.path.to.ImplementationType") {
((ImplementationType)interfaceType).doSomethingOnlyICanDo();
}
} catch (Exception e) {
e.printStackTrace();
}
Questo sembra piuttosto brutto, e rovina la bella config -avviato il processo che hai Non ti suggerisco di farlo, è solo un esempio.
2. Un'altra opzione che avete è quella di estendere la riflessione a partire da soli Class
/Object
creazione per includere Method
riflessione. Se è possibile creare Class
da una stringa trasferita da un file di configurazione, è anche possibile passare un nome di metodo da tale file di configurazione e, tramite riflessione, ottenere un'istanza dello Method
dall'oggetto Class
. È quindi possibile chiamare invoke
(http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object, java.lang.Object ...)) su Method
passando l'istanza della classe creata. Penso che questo ti aiuterà a ottenere ciò che cerchi.
Ecco un codice per servire da esempio. Nota che mi sono preso la libertà di codificare i parametri per i metodi. Potresti specificarli anche in una configurazione e riflettere sui nomi delle loro classi per definire i loro obietti e istanze Class
.
public class Foo {
public void printAMessage() {
System.out.println(toString()+":a message");
}
public void printAnotherMessage(String theString) {
System.out.println(toString()+":another message:" + theString);
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("Foo");
Method method1 = c.getDeclaredMethod("printAMessage", new Class[]{});
Method method2 = c.getDeclaredMethod("printAnotherMessage", new Class[]{String.class});
Object o = c.newInstance();
System.out.println("this is my instance:" + o.toString());
method1.invoke(o);
method2.invoke(o, "this is my message, from a config file, of course");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException nsme){
nsme.printStackTrace();
} catch (IllegalAccessException iae) {
iae.printStackTrace();
} catch (InstantiationException ie) {
ie.printStackTrace();
} catch (InvocationTargetException ite) {
ite.printStackTrace();
}
}
}
e la mia uscita:
this is my instance:[email protected]
[email protected]:a message
[email protected]:another message:this is my message, from a config file, of course
Dove posso scaricare il vaso per i metodi '' InterfaceType' e ImplementationType'? –