0

I have the following structure. A parent class:

public class MyTree<E extends MyTree<E>>{
   List<E> children;

   public MyTree(List<E> ls){
      this.children = ls;
   }
   
   public void insert(E t){
     this.children.add(t);
   }
}

a child class:

public class SpecTree<E> extends MyTree<SpecTree<E>>{
   private E value;

   public SpecTree(E value){
      super(new ArrayList<>());
      this.value = value;
   }
}

Now from main, I want to insert a tree into another tree.

SpecTree<Number> st = new SpecTree<>(0);
st.insert(new SpecTree<Integer>(2));      //incompatible type error

The SpecTree must be able to accept new children with values that are subtype of the current tree. For example, I should be able to insert a SpecTree<Integer> into SpecTree<Number>.

Is it possible to do without changing the structure of code and changing only the type parameters?

vortex
  • 117
  • 7
  • @sweeper I still get the incompatible type error. – vortex May 11 '22 at 10:18
  • 1
    Oops I misread your code. You'd need `class MyTree>` and `class SpecTree extends MyTree>`. Does that constitute "changing the structure of code"? – Sweeper May 11 '22 at 10:28
  • Thanks it solved the problem. Maybe you just add this as an answer and I mark it as solution. – vortex May 11 '22 at 10:35

1 Answers1

2

The error occurs because insert expects SpecTree<Number>, but we are giving it SpecTree<Integer>.

According to PECS, insert would be able to take both SpecTree<Number> and SpecTree<Integer> if it had took a SpecTree<? extends Number>. A producer of integers is a consumer of numbers.

That means changing E to SpecTree<? extends E>:

public void insert(E t)

Therefore:

class SpecTree<E> extends MyTree<SpecTree<? extends E>>

However, now the type argument SpecTree<? extends E> does not fit the bound specified in MyTree, which is E extends MyTree<T>, so we change that too:

class MyTree<E extends MyTree<? extends E>>
Sweeper
  • 213,210
  • 22
  • 193
  • 313