Let's say I have an abstract base class defined in a library (library.jar):
package library;
public abstract class BaseClass {
public BaseClass() {}
//Takes a fully qualified class name eg. library.SubClassLibrary
//And returns a default instance via reflection
public BaseClass createFromFullyQualifiedName(String className) {
Class<?> clazz = null;
BaseClass baseClass = null;
try {
clazz = Class.forName(className);
baseClass = (BaseClass) clazz.newInstance();
}
catch(Exception ex) {
throw new RuntimeException(ex.getMessage());
}
return baseClass;
}
}
If I add a subclass to the base class in the library...
package library;
public class SubClassLibrary extends BaseClass {
public SubClassLibrary () {}
}
...I can use createFromFullyQualifiedName without issue:
SubClassLibrary scl =
(SubClassLibrary) BaseClass.createFromFullyQualifiedName("library.SubClassLibrary"); //<-- SUCCESS!
However, if I reference the library in an application and extend the base class there...
package application;
import library.BaseClass;
public class SubClassApp extends BaseClass {
public SubClassApp() {}
}
...attempting to create this application-defined sub class fails
SubClassApp sca =
(SubClassApp) BaseClass.createFromFullyQualifiedName("application.SubClassApp"); //<-- RUNTIME EXCEPTION!
This is happening, presumably, because the library doesn't have SubClassApp in its classpath and has no knowledge of it existing. I am trying to allow my users to select their BaseClass implementation (including those defined outside my library) via a mutable config file that I parse out a fully qualified class name from. I don't want my users to be forced to do reflection outside of my library -- I would prefer to acquire the BaseClass instance myself just from the fully qualified class name string without asking users to pass my library a Class<?> object. Is there a way to make my library "aware" of subclass implementations outside of the library at runtime without asking my users to do reflection themselves?
PS: I am aware that newInstance() is considered evil by some. If it helps, we can pretend I'm using getConstructor() instead. The same problem remains.
Thanks for any help!
Aucun commentaire:
Enregistrer un commentaire