1

I have an abstract java class that looks like:

public abstract class X  {
    public abstract void commonFunction();
}

I also have a bunch of maps, that I would like to be like this:

Map<String,A> mapA = new HashMap<String,A>();
Map<String,B> mapB = new HashMap<String,B>();
Map<String,C> mapC = new HashMap<String,C>();
Map<String,D> mapD = new HashMap<String,D>();
Map<String,E> mapE = new HashMap<String,E>();

A, B, C, D and E all extend X so they all implement commonFunction().
I'd like to be able to call a function like this:

someFunction(mapA); // or someFunction(mapB) etc.

...where someFunction looks like:

void someFunction(Map<String,X> mapX) {
    ...some stuff
    x.commonFunction();
    ...more stuff
}

But the compiler complains with the things I've tried, which includes:

  • changing the map declarations (left-hand side) by replacing [ABCDE] with X
  • casting the map into Map<String,X> inside the someFunction function call

Also tried with an implemented interface instead of an extended class. Not sure what I'm doing wrong.

Edit:
I'm sorry, I rushed the question so I made a mistake. My maps are actually:

Map<String,List<A>> mapA = new HashMap<String,List<A>>();

...and so the someFunction signature is actually:

void someFunction(Map<String,List<X>> mapX) 

I'm not sure if that makes a big difference.

4 Answers 4

2

Try declaring

<T extends X> void someFunction(Map<String,List<T>> mapX)

Even A being a subclass of X, Map<String,List<A>> is not a subclass of Map<String,List<X>>.

You need to use a generic method as above to have a parameter that accepts any Map<String, List<any class that extends X>> ("any class that extends X" is represented by the type parameter T).

Sign up to request clarification or add additional context in comments.

2 Comments

Yep, this did the trick. There's other correct answers around but the explanation is good and you got there first!
Is there any serious issues if I wanted to change X to be an interface instead of a class? The compiler doesn't seem to mind if I leave everything as it is except change the definition of X to an interface, but if I change your code above to <T implements X> the compiler doesn't like it.
1

But the compiler complains with the things I've tried

The rules of polymorphism does not apply to generics.

List<X> list = new ArrayList<A>; // Invalid. Polymorphism does not in declaration or referencing

However, this is valid:

List<X> list = new ArrayList<X>;
list.add(new A()); // Can add sub-type of X
list.add(new B());

Try this:

void someFunction(Map<String,? extends X> mapX) {

Comments

0

You can't call X in your method, you must access it through the Map, like so

mapX.get("myKey").commonFunction();

Just tested it with this:

void tester() {
    Map<String, X> testMap = new HashMap<String,X >();
    testMap.put("myKey", new A());
    someFunction(testMap);
}

void someFunction(Map<String, X> myMap) {
    myMap.get("myKey").doSomething();
}

abstract class X {
    abstract void doSomething();
}

class A extends X {
    @Override
    void doSomething() {
        System.out.println("I'm A");
    } 
}

class B extends X {
    @Override
    void doSomething() {
        System.out.println("I'm B");
    } 
}

class C extends X {
    @Override
    void doSomething() {
        System.out.println("I'm C");
    } 
}

Comments

0

This should work:

<K extends X> void someFunction( Map<String, List<K>> mapX ) {
    for ( List<K> list : mapX.values() ) {
        for ( X obj : list ) {
            obj.commonFunction();
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.