0

I have the following code (simplified, to show the problem core):

public interface IElement {}


public interface IDataSet<E extends IElement> {}


public interface IPropertyTranslator<D extends IDataSet<? super E>, E extends IElement> {}


public interface IElementTranslator<D extends IDataSet<?>> {}


public class AnimalElement implements IElement {}


public class AnimalDataSet implements IDataSet<AnimalElement> {}


public class AnimalPropertyTranslator implements IPropertyTranslator<AnimalDataSet, AnimalElement> {}


public class UniversalPropertyTranslator implements IPropertyTranslator<IDataSet<IElement>, IElement> {}


public class ElementTranslator<D extends IDataSet<? super E>, E extends IElement> implements IElementTranslator<D> {

    public Collection<IPropertyTranslator<? super D, ? super E>> propertyTranslators = new HashSet<>();

}


public class Demo {

    public static void demo() {
        ElementTranslator<AnimalDataSet, AnimalElement> animalElementTranslator = new ElementTranslator<>();
        animalElementTranslator.propertyTranslators.add(new AnimalPropertyTranslator());
        animalElementTranslator.propertyTranslators.add(new UniversalPropertyTranslator());
    }

}

Unfortunately, the last line of the demo method yields the following error: The method add(IPropertyTranslator<? super AnimalDataSet,? super AnimalElement>) in the type Collection<IPropertyTranslator<? super AnimalDataSet,? super AnimalElement>> is not applicable for the arguments (UniversalPropertyTranslator). Through random trials I discovered, that the problem is probably connected with the <D extends IDataSet<? super E>, E extends IElement> expression, although I still do not know how to fix it.

In the meantime the following variantion of the code works perfectly:

public interface IDataSet {}


public interface IPropertyTranslator<D extends IDataSet> {}


public interface IElementTranslator<D extends IDataSet> {}


public class AnimalDataSet implements IDataSet {}


public class AnimalPropertyTranslator implements IPropertyTranslator<AnimalDataSet> {}


public class UniversalPropertyTranslator implements IPropertyTranslator<IDataSet> {}


public class ElementTranslator<D extends IDataSet> implements IElementTranslator<D> {

    public Collection<IPropertyTranslator<? super D>> propertyTranslators = new HashSet<>();

}


public class Demo {

    public static void demo() {
        ElementTranslator<AnimalDataSet> animalElementTranslator = new ElementTranslator<>();
        animalElementTranslator.propertyTranslators.add(new AnimalPropertyTranslator());
        animalElementTranslator.propertyTranslators.add(new UniversalPropertyTranslator());
    }

}

I do not understand why the second generic part of the interface causes the code to behave differently.

Radosław Łazarz
  • 850
  • 1
  • 9
  • 21
  • Possible duplicate of [Difference between super T> and extends T> in Java](http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java) – Murat Karagöz Feb 10 '17 at 14:56
  • Possible, but I read the documentation scepifying difference between super and extends and used it in interfaces as I intended them to function. The problem is: why `Collection>` does not accept `IPropertyTranslator, IElement>`? – Radosław Łazarz Feb 10 '17 at 14:58

1 Answers1

0

The solution is slightly related to the "Producer Extends, Consumer Super" rule. In the problem code one need to change the following headers into those below:

public interface IPropertyTranslator<D extends IDataSet<? extends E>, E extends IElement> {}

public class UniversalPropertyTranslator implements IPropertyTranslator<IDataSet<? extends IElement>, IElement> {}

and everything would be working just fine.

Radosław Łazarz
  • 850
  • 1
  • 9
  • 21