Reputation:
Is there a way to instantiate all children of an abstract class dynamically?
What I have currently is similar to this:
public class CommandHandler {
private Command info = new Info();
private Command prefix = new Prefix();
private Command roll = new Roll();
private Command coin = new Coin();
private Command invite = new Invite();
private Command quit = new Quit();
private Command restart = new Restart();
}
With the abstract parent class being something like this:
public abstract class Command {
protected String name;
protected String arguments;
protected abstract void execute();
}
But what if I want to instantiate all classes that extend Command without typing them all out individually and adding to the list every time I add a command?
And if I can instantiate them dynamically, can I also manipulate them dynamically? i.e. add each class to a list once it has been instantiated.
Or is there a better design to use that accomplishes what I want in a simpler way?
EDIT: @Ash's solution works perfectly in an IDE, but not when using a jar. All you have to do to make it work in both is change
classPathList.addAll(ClasspathHelper.forClassLoader());
to
classPathList.addAll(ClasspathHelper.forJavaClassPath());
Hope it helps someone!
Upvotes: 4
Views: 640
Reputation: 3457
If you use maven (if not, you should :p), add the following dependency :
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
Then you can list the class you want with the following code (assuming you have a constructor with no parameters) :
public class Loader {
public static void main(String[] args) {
try {
Set<URL> classPathList = new HashSet<URL>();
classPathList.addAll(ClasspathHelper.forClassLoader());
Set<Class<? extends Command>> result = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner()).setUrls(classPathList)).getSubTypesOf(Command.class);
List<Command> commands = new ArrayList<Command>();
for (Class<? extends Command> c : result) {
System.out.println(c.getSimpleName());
commands.add(c.newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Upvotes: 3