halloei
halloei

Reputation: 2036

Method from superclass cannot be overridden when return type is a List

When I want to return a ArrayList of C2, it's not possible, because the return types are incompatible.

package a;
class C1 {
  private final ArrayList<C2> c2s = new ArrayList<C2>();

  protected ArrayList<C2> getC2() { return c2s; }
}

class C2 {}

package b;
class C1 extends a.C1 {
    private final ArrayList<C2> c2s = new ArrayList<C2>();

  @Override
  protected ArrayList<C2> getC2() { return c2s; } // won't work
}

class C2 extends a.C2 {}

Update: Why doesn't this work, when following works (in a.C1 and b.C1):

private final C2 c2 = new C2();

public C2 getC2() { return c2; }

Upvotes: 0

Views: 88

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500785

You've got two different C2 classes - an ArrayList<a.C2> isn't the same as an ArrayList<b.C2>. They're incompatible to avoid this sort of thing:

ArrayList<b.C2> listB = new ArrayList<b.C2>();
ArrayList<a.C2> listA = listB; // This is invalid...
listA.add(new a.C2());
b.C2 firstElement = listB.get(0); // To stop this from causing problems.

That has nothing to do with overriding, it's just normal generics. You could change your declaration in a.C1 to:

protected ArrayList<? extends C2> getC2() { return c2s; }

Then it would work, because the types will be compatible. That prevents the above abuse because you can't call add on an ArrayList<? extends a.C2>.

As an aside, I would strongly discourage you from having class names which are only distinguished by package. It's a recipe for unreadable code and painful debugging sessions. It's also a recipe for hard-to-read questions, so if your real code doesn't use this nasty naming scheme, please don't make your sample code use it either.

Upvotes: 1

Related Questions