I had an error while generalizing some classes in order to reduce code duplicates in my project, the case is as follows:
interface ClassRoot{}
public class ClassChild1 implements ClassRoot{
// constructor is omitted for simplicity
public Collection<ClassChild1> createList(){
Collection<ClassChild1> col = getCollectionFromSomewhere();
return col;
}
}
public class Class1{
protected <T extends ClassRoot> Collection<T> doSth(){
Collection<T> myCol = null;
ClassChild1 child = new ClassChild1();
// here I get compile time assignment error
// also (assuming that myCol not null) myCol.add(new ClassChild1());
// is not permitted.
myCol = child.createList();
return myCol;
}
}
Isn't that against the polymorphism phenomenon? I know that for example,
List<Object> list1;
can never be (and should not be assigned for typesafety) to:
List<String> list2;
But here my case is different, i specified the Type Parameter extending some specific class expecting to make use of OOP Polymorphism concept, and doing assignments right exactly implementing right class. Now I have 2 questions;
The assignment
Collection<T> myCol = null;
myCol = child.createList();
will fail because you are assigning Collection<ClassChild1>
to a Collection
parameterized with an unknown type T
, which may or may not be ClassChild1
.
You have specified T
as inferred at the call site, so imagine the following code:
Class1 c1;
Collection<ClassChild2> c = c1.doSth();
You can see that the compiler would paint itself into a corner if it allowed you to compile such a doSth
method since inside that method you want to add a ClassChild1
instance to a collection that in this example happens to hold instances of ClassChild2
.