简体   繁体   中英

Java referring to uninitialized class

I have a superclass with 6 subclasses. I have a hashmap with string keys and subclass-collection values. I'm defining a method that can take as argument a superclass and put it into the correct collection within the hashmap. To find the correct key I use "istanceof". Now when I try to add the superclass-argument to the unlocked key I expect (I can't actually compile my program) a compile-time error because I haven't casted. I can't make a variable refer to a class. It needs to refer to an object as far as I know. I can make it refer to Class<Subclass>. But I still can't progress from there.

    public void addCard(AttackCard card) {
    String category = null;
    AttackCard type = null; <-- I would like to make this refer to e.g. Assassin
    if (card instanceof Assassin) {
        category = "assassins";
    }if (card instanceof Fighter) {
        category = "fighters";
    }if (card instanceof Mage) {
        category = "mages";
    }if (card instanceof Marksman) {
        category = "marksmen";
    }if (card instanceof Support) {
        category = "supports";
    }if (card instanceof Tank) {
        category = "tanks";
    }
    attackPool.get(category).get(card.getTier()).add(card)
}

2 things to note:

1) the subclasses are abstract and can't be initialized?

2) my hashmap is actually HashMap<String, Hashmap<Enum, ArrayList<Subclass>>>

so how should I cast my card to be of a specific subclass?

Add a new enum called CardType which will have values Assassin , Fighter etc. then add a new method to your card class getType() .

class AttackCard{
  CardType type;

  ...

  CardType getType(){
     return type;
  }

}

then you can change your Map<String, map<Enum, ArrayList<Subclass>>> into a Map<CardType, map<Enum, List<AttackCard>>>

attackPool.get(card.getType()).get(card.getTier()).add(card)

On a related Note, it's not good practice to force Map and List implementations in your type declaration because then you won't be able to change it later and might expose implementation details.

For example instead of HashMap<String, Hashmap<Enum, ArrayList<Subclass>>> you should make it Map<String, map<Enum, List<Subclass>>> .

Also if your key in a map is an Enum, its more efficent to use an EnumMap instead of HashMap

Boris is rigth.

To keep it simple, just add a addToPool(Map<String, EnumMap <Enum, List<AttackCard >>> pool) to your AttackCard class and implement it in each subclass to add itself to the right category.

This said, some remarks.

Casting is rarely a good idea and often denotes a design problem.

I don't really see the interest of storing the cards in different submap as you will have to cast it when retrieving it (in order to call subclass specific method). (You can't type your submap list as a subclass without restricting the entire pool to this subclass only).

If I were you I'd design the pool as an object with several attributes of type List<PeculiarSubclass>

Otherwise this has nothing to see with generics and i don't really understand how you could have abstract classes at the bottom of the hierarchy. Only AttackCard should be abstract or an Interface

I'm not sure I understood, but maybe this is what you need:

public void addCard(AttackCard card) {
    String category = null;
    if (card instanceof Assassin) {
    category = "assassins";
       Assassin type = (Assassin) card;
       // Other code using card as Assassin
    } else if (card instanceof Fighter) {
        category = "fighters";
        Fighter type = (Fighter) card;
       // Other code using card as Fighter
    } else if ...

This looks quite strange however. I don't know what you are trying to accomplish, but I think you need to understand better how to use inheritance (or to clarify what you want to do).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM