RTF
RTF

Reputation: 6484

Trouble with Java inheritance

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:

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.

Upvotes: 1

Views: 82

Answers (4)

ericbn
ericbn

Reputation: 10948

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).

Upvotes: 2

Matt MacLean
Matt MacLean

Reputation: 19648

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();
        }
    }
}

Upvotes: 0

Ankur Shanbhag
Ankur Shanbhag

Reputation: 7804

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) {

Upvotes: 1

user184994
user184994

Reputation: 18271

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");
    } 
}

Upvotes: 0

Related Questions