Clarifying Java generics
I have the following code:
interface Id{
int getA();
}
class Id1 implements Id{
@Override
public int getA() {
return 0;
}
}
class Id2 implements Id{
@Override
public int getA() {
return 0;
}
public int getB(){
return 2;
}
}
interface Container<I extends Id, C extends Container<I,C>>{
C withInt(int a);
}
class DefaultContainer<I extends Id> implements Container<I, DefaultContainer<I>>{
@Override
public DefaultContainer<I> withInt(int a) {
return new DefaultContainer<>();
}
}
class SpecialContainer<I extends Id> extends DefaultContainer<I>{
@Override
public SpecialContainer<I> withInt(int a) {
return new SpecialContainer<>();
}
}
interface ContainerGroup<C extends Container<? extends Id, C>>{
Stream<C> getContainers();
}
class DefaultContainerGroup<DC extends DefaultContainer<? extends Id>>
implements ContainerGroup<DC>{
//Error:(36, 35) java: type argument DC is not within bounds of type-variable C
@Override
public Stream<DC> getContainers() {
//can return:
// [ DefaultContainer<Id>, DefaultContainer<Id2>, ... ] OR
// [ SpecialContainer<Id>, SpecialContainer<Id2>, ... ]
return null;
}
}
And the problem is in the last error: (36, 35) java: DC type argument is not within C type constraints.
Within a container group, I can store containers with type IDs. I am guessing there is no better way to store this than? At runtime, I will have to use instanceof to check Id1 or Id2 in order to access the getB () getter. If it was behavior (not data), I could have a generic method in the Id interface, but since this is data only present in Id2, I suppose downcasting is only a way?
UPDATE
This actually solves the ERROR, but don't know why the first solution doesn't work:
interface ContainerGroup<C extends Container<? extends Id, ? extends Container>>{
Stream<C> getContainers();
}
source to share
I think I can see what's going on.
B DefaultContainerGroup
, DC extends DefaultContainer<? extends Id>
means "something derived from DefaultContainer
".
B ContainerGroup
, C extends Container<? extends Id, C>
means "exact C
, used as an argument for Container
".
Means itself DefaultContainer
would be acceptable, but the classes derived from it are not.
source to share