简体   繁体   中英

Passing a superclass object as a parameter to a method with a subclass parameter

In the below code 'NPC' and 'Settlement' are both subclasses of the superclass 'Feature' (I have removed irrelevant parts of the generateNewRelationships() method)

public ArrayList<Relationship> generateNewRelationships(ArrayList<Feature> features) {
    for(Feature feature: features) {
        ArrayList<Predicate> possiblePredicates = filterPredicates(feature, subjectPredicates);
    }
}

private ArrayList<Predicate> filterPredicates(NPC npc, ArrayList<Predicate> npcPredicates) {
    // Does NPC filter
}

private ArrayList<Predicate> filterPredicates(Settlement settlement, ArrayList<Predicate> settlementPredicates) {
    // Does Settlement filter
}

Now the call of the filterPredicates method doesn't work as there is no method that takes 'Feature' as a parameter type. Is there a way to cast the 'feature' variable so that it is casted as the subtype that it is actually referencing, so that the correct method is used?

I want to avoid manually writing out a if/else or switch statement, as in future there will be more subclasses of Feature.

There will never be an instance of a 'Feature', only instances of its subclasses, so the ArrayList features will only ever contain NPCs or Settlements.

(This is a repost of my question as it was closed saying PECS (Producer Extends Consumer Super) was the solution, but that is about passing collections as parameters. My question is asking about how to write the call to 'filterPredicates(feature, subjectPredicates)' where an individual object 'feature' will alternate between Feature subtypes 'NPC' and 'Settlement' within the for loop, so that 'feature' is cast as an NPC or a Settlement, depending on what subtype 'feature' actually holds at that time.)

As Tintin mentioned, without more example code & detail it is difficult to give a really good answer.

But you have one specific question which can be answered: "Is there a way to cast the 'feature' variable so that it is casted as the subtype that it is actually referencing, so that the correct method is used?"

If you want to cast Feature to a subtype, you'll need to first identify which subtype you want to cast to. If there are many possible subtypes, you would need to check which one it is using instanceof . But you mentioned you don't want to do this.

So in order to avoid the instanceof checking, you need to work with Feature instead of the subclasses.

One possible option here is to simply update the Feature interface so it can be used for what you want to do. You can add a function to Feature called matchesPredicate and implement it differently for NPC and Settlement . Then filterPredicates can change to something like this:

// matchesPredicate looks like this: "public boolean matchesPredicate(Predicate p){...}"

private ArrayList<Predicate> filterPredicates(Feature feature, ArrayList<Predicate> predicates) {
    
   ArrayList<Predicate> result = new ArrayList();
   for (Predicate p : predicates) {
       if (feature.matchesPredicate(p)) {
           result.add(p);
       }
   }

   return result;
}

(Note: At the time of this answer you didn't write what the filterPredicates function body does so I am guessing a bit here with that code.)

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