2014-11-27 18 views
5

Ein Freund von mir hat dieses Schmankerl in dem Java-API (https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html),Verwendungen von rekursiven Grenzen

Class Enum<E extends Enum<E>> 

und durch den folgenden Artikel https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html Lese ich verstehen konnte, was die zuvor erwähnte Linie syntaktisch brachte aber aus den Beispielen Da ich keinen Anwendungsfall für die Enum-Klasse gefunden habe (überprüfte die Quelle).

Ich möchte mehr über mögliche Probleme erfahren, wo das oben genannte eine Lösung darstellen kann.

Antwort

4

Es ist zum Beispiel nützlich, um Unterklassen zu ermöglichen, ihre eigene Art

Stellen Sie sich eine Klasse wie

class Node { 
    Node next; 
} 

zu verwenden, wenn Sie diese Klasse erweitern, sind Sie mit Node stecken.

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

Sie können es auch definieren nicht nur wie

class Node<T> { 
    T next; 
} 

denn das alles für T erlauben würde. Sie wollen wirklich eine T, dass extends Node oder Sie können nicht mehr T als Node innerhalb Node ohne Gießen. Es würde jedoch für Kinderklassen funktionieren.

Durch die Verwendung von rekursiven Grenzen wie

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

Sie T beschränken zu sich selbst oder Subklassen von sich selbst, die dann können Sie

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

auf diese Weise beide Eltern und Kind Klasse alles zugreifen können tun auf ihre Abstraktionsniveau vollständig typsicher.

2

Im Allgemeinen ist es nützlich, etwas Verhalten in einer Oberklasse (z. B. in Enum) zu definieren, die von Typinformationen abhängt, die für einen Subtyp der betreffenden Klasse spezifisch sind (I actually asked a similar question a wee while ago).

+0

Ich denke nicht, dass diese Frage mit Ihrer Frage identisch ist.(Dieser hat nichts mit Klassenliteralen zu tun.) – Radiodef

+0

Ja, ich glaube, ich bin ein bisschen zu weit gesprungen. Dennoch gibt es immer noch Informationen über den Untertyp an die Oberklasse weiter, wenn auch nur zur Kompilierungszeit (z. B. für Methodensignaturen). – errantlinguist

+0

P.S. Sollte ich die Antwort löschen, da ich gestehe, dass sie falsch ist, oder sollte sie bleiben? - Ich habe das Ganze noch nie herausgefunden ... – errantlinguist

2

Dieses Idiom bedeutet fast immer 'E sollte der Typ der Unterklasse' sein. Zum Beispiel könnten Sie feststellen, dass Enum implements Comparable<E>.

Wenn die Klasse erweitert wird, erhalten Sie so etwas wie:

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

Jetzt AnEnum ist auch ein Comparable<AnEnum> und getDeclaringClass gibt einen Class<AnEnum>.

Ich habe dieses Idiom im Zusammenhang mit der curiously recurring template pattern gesehen. Die Absicht ist, dass die Oberklasse sich generisch auf die Unterklasse beziehen kann.

(Aufgrund der Tatsache, dass die Unterklasse von Enum vom Compiler erzeugt wird, das glaube ich nicht, dass es tatsächlich ein Enum Grund insbesondere erforderlich, um auf diese Weise erklärt werden. Es ist einfach Enum<E> gewesen sein könnte.)

+0

Dies ist das richtige Muster, nicht das in meiner Antwort +1 – errantlinguist

Verwandte Themen