Uses of recursive type bounds

大兔子大兔子 提交于 2019-12-01 18:12:41

It's for example useful to to allow subclasses to use their own type

Imagine a class like

class Node {
    Node next;
}

if you extend that class, you're stuck with Node.

class SpecialNode extends Node {
    void foo() {
        // euwww
        SpecialNode nextNode = (SpecialNode) this.next;
    }
}

You also can't just define it like

class Node<T> {
    T next;
}

because that would allow anything for T. You really want a T that extends Node or you can no longer use T as Node from within Node without casting. It would work for child classes though.

By using recursive bounds like

class Node<T extends Node<T>> {
    T next;
}

You limit T to yourself or subclasses of yourself which then allows you to do

class SpecialNode extends Node<SpecialNode> {
    void foo() {
        SpecialNode nextNode = this.next; // type-safe!
    }
}

That way both parent and child class can access everything on their abstraction level fully typesafe.

This idiom almost always means 'E should be the type of the subclass'. For example, you might notice that Enum implements Comparable<E>.

When the class is extended, you get to something like:

//         E extends Enum<E> ┐
class AnEnum extends Enum<AnEnum> {...}

Now AnEnum is also a Comparable<AnEnum> and getDeclaringClass returns a Class<AnEnum>.

I've seen this idiom related to the curiously recurring template pattern. The intent is that the superclass can refer to the subclass generically.

(Due to the fact that the subclass of Enum is generated by the compiler, I don't think there is actually a reason Enum in particular needed to be declared this way. It could have just been Enum<E>.)

Generally it's useful for defining some behavior in a superclass (e.g. in Enum) which depends on type information specific to a subtype of the class in question (I actually asked a similar question a wee while ago).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!