Home > Software design >  Java - Get instance of each subclass
Java - Get instance of each subclass

Time:06-10

I have an abstract class Command. The constructor looks like this:

public Command(String cmd, String helpMsg, String... args) {
    this.command = cmd;
    this.helpMsg = helpMsg;
    this.args = args;
}

Whenever a certain condition is met, I want to be able to print out each command, it's help message and arguments.

If I could loop through the instances of the subclasses of Command, I could call the getter functions for these attributes. However, I don't know how I could store instances like this. I've been reading about generics but haven't been able to solve this problem yet.

Right now I have another class with this code:

private static Map<Class<? extends Command>, ? extends Command> instances;

public static <T extends Command> void addInstance(Class<T> tClass, T tInstance) {
    instances.put(tClass, tInstance);
}

But it gives me this error:

Required type: capture of ? extends Command

Provided: T

It would also be nice if I were able to get instances to individual subclasses with getInstance(subclass.class)

CodePudding user response:

If you want to ensure that the class and object are of the same type, you’re going to need to make your own mapping class which enforces that, or use an existing one like Guava’s ClassToInstanceMap.

If it’s sufficient for you to simply put and get a Command instance out of your map given a class, then I’d recommend simply dropping the second wildcard:

private static Map<Class<? extends Command>, Command> instances;

There are a lot of great existing answers which explain the behavior of the extends wildcard and why you’re getting the warning that you are when attempting to insert one of your command instances. I definitely recommend giving them a read: Difference between <? super T> and <? extends T> in Java

CodePudding user response:

This can be achieved by creating special kind of Map where keys type is bound to values type:

    public class BoundMap<T> extends HashMap<Class<? extends T>, T> {
    }

Then the code becomes:

    private static BoundMap<Command> instances;

    public static <T extends Command> void addInstance(Class<T> tClass, T tInstance) {
        instances.put(tClass, tInstance);
    }
  • Related