Why does this not work...
public ArrayList getEdges() {
return A;
//A is an Arraylist of type \'Action\'. Action implements Ed
Because the generic type must always be the same, not something that extends from it you can rewrite like this for it to work:
public ArrayList<? extends Edge> getEdges() {
return A;
//A is an Arraylist of type 'Action'. Action implements Edge.
}
A banana is a fruit. A list of bananas is not a list of fruit.
Oherwise someone could construct a list of bananas, pass you a reference to a list of fruit, and you'd (correctly) insert an apple in it. The owner of the list of the bananas would be rightfully surprised.
This is because ArrayList<E>
is not covariant on the type E
. That is, you cannot substitute an instance of ArrayList<Derived>
for ArrayList<Base>
just because Derived
inherits from Base
.
Consider this case: String
inherits from Object
; however, if this meant you could use an ArrayList<String>
as an ArrayList<Object>
then the following code would be possible:
ArrayList<Object> list = new ArrayList<String>();
list.add(new Integer(5)); // Integer inherits from Object
The above can't work, because you can't add an Integer
to an ArrayList<String>
. If you could, then this could happen:
ArrayList<String> stringList = (ArrayList<String>)list;
String string = stringList.get(0); // Not a string!
As Ziyao has indicated, the correct way to implement this is to use the ? extends Edge
syntax.
Because while Edge
is a subtype of Action
, ArrayList<Action>
is not a subtype of ArrayList<Edge>
.
Use ArrayList<? extends Edge>
instead.
You could take a look at this tutorial's 4. Wildcard section, although I'd suggest to just read through it, because it is really helpful.