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

      

+3


source to share


1 answer


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.

0


source







All Articles