3

I have the following class hierarchy by now:

interface Interface<T> {
    boolean isGreaterThan(T other);
}
class Base implements Interface<Base> {
    public boolean isGreaterThan(Base other) {
        return true;
    }
}
class Subclass extends Base {
    ... //note that I dont need to implement or overwrite isGreaterThan() here
}
class Wrapper<E extends Interface<E>> {
    protected List<E> list;
    ...
}
class Test {
    public static void main(String[] args) {
        Wrapper<Subclass> = new Wrapper<Subclass>(); //This line produces the error
    }
}

I get the following error message:

Type parameter 'Subclass' is not within its bound; should implement 'Interface<Subclass>'

My Question is: How can I tell java, that the Interface should accept any element E which extends T? Or is the reason in Wrapper? I tried for the Wrapper:

class Wrapper<E extends Interface<? extends E>> {}

which rather produced errors in the body of wrapper, and did not change the original error.

Wrapper<Base> wrapper = new Wrapper<Base>();

works just fine... how can I make

Wrapper<Subclass> wrapper = new Wrapper<Subclass>();

work as well? Is there a clean way without any casts? (Wildcards allowed)

Thanks!

ElectRocnic
  • 1,275
  • 1
  • 14
  • 25
  • 2
    `class Wrapper>` – ZhongYu Nov 28 '16 at 15:44
  • This does not change anything, thank you for your help! – ElectRocnic Nov 28 '16 at 15:47
  • ` super E>` :) see also example https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort(java.util.List) – ZhongYu Nov 28 '16 at 15:53
  • I tried it, but the error is still there ;-) – ElectRocnic Nov 28 '16 at 15:55
  • Ohhh, I had other errors which complicated your suggestion, but I could figure out, this was because of inner-class generics, and I just had to put your '? extends' solution there too... now the whole thing works! Thanks so much! Do you want to post this as answer, so I can mark it as the answer? – ElectRocnic Nov 28 '16 at 16:09

2 Answers2

2

Do something like this:

class Base<T extends Base<T>> implements Interface<T> {
    public boolean isGreaterThan(T other) {
        return true;
    }
}

And:

class Subclass extends Base<Subclass> {
    ... //note that I dont need to implement or overwrite isGreaterThan() here
}
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • Thank you very much for the first approach! It works for every subclass now, but no more for the base class itself? I mean: Wrapper wrapper = new Wrapper() will produce the error now, while Wrapper will work :/ Thank you for your help! – ElectRocnic Nov 28 '16 at 15:45
  • Because `Base` is now a generic class, so `Base` without a type argument, which you are using in `Wrapper`, is a [raw type](http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it). – Jesper Nov 28 '16 at 15:48
  • I tried to figure out a workaround, but I failed. Can you give me perhaps another hint? I would be grateful! – ElectRocnic Nov 28 '16 at 16:02
  • The answer of Zhong Yu works for every case! Thanks nevertheless! – ElectRocnic Nov 28 '16 at 16:10
2

try

class Wrapper<E extends Interface<? super E>>

just like Comparable, it is intuitively a 'contra-variant' type, therefore in most cases it should be used with <? super>. For example Collections.sort

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • By the way: I had an inner class, which uses the same interface, thus I had to add super E> to the Inner Class definition as well! – ElectRocnic Nov 28 '16 at 16:28