Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type mismatch: cannot convert MyClass<E> to MyClass<E>

There is something I am missing about generics and/or inner classes. I want to write a specialized tree class, with a specialized iterator. How can class FooTree have an iterator that returns successive nodes of type FooTree rather than node values of type V? The class starts:

public class FooTree<V>
   private final V value;
   private FooTree<V> left;
   private FooTree<V> right;

I made the Iterator class an inner class since nobody else will care about it. The factory method defined in FooTree to get an iterator is:

public Iterator<FooTree<V>> preorderIterator() {
    return this.new PreorderIterator<FooTree<V>>;
}

Since next() must return a V, as declared in the interface, I added nextNode() to get around the return type. The inner class starts:

private class PreorderIterator<V> implements Iterator<V> {
   private FooTree<V> current;  
   . . .
   public FooTree<V> nextNode() {
      current = FooTree.this;                        **

I get this wonderful compiler error:
Type mismatch: cannot convert from ...FooTree<V> to ...FooTree<V> (both are the same package)
Eh wot!?
I can make it compile by adding a cast: current = (FooTree)FooTree.this; But why should I have to in the first place? Is it trying to be "smart" and figuring the first V might be different from the second V?

What is the right way to do this?

like image 682
Allan Terry Avatar asked Dec 22 '25 17:12

Allan Terry


1 Answers

Try making your declaration:

private class PreorderIterator implements Iterator<V>

The <V> in your inner class is unnecessary, and in this case, unhelpful.

What's actually happening is that the <V> in PreorderIterator<V> is "shadowing" the <V> from your outer class, so that although they look like they're the same type parameter, they're actually different parameters that happen to have the same name.

like image 158
Simon Nickerson Avatar answered Dec 24 '25 06:12

Simon Nickerson