2009-03-29 8 views
4

eine Klassenhierarchie gegeben, in dem die Basisklasse eine rekursive Selbsttyp definiert:Java-Feldtyp für einen Wert eines generisch rekursiven Selbst-Typs?

abstract class A<T extends A<T>> { } 

Wie kann ich eine andere Klasse zu erklären (die nicht in T generisch sein sollte, weil eine solche T über die gesamte Lebensdauer der variieren Objekt) mit einem Feld, das jede Unterklasse von A enthalten kann?

Die folgende funktioniert nicht:

public class B { 
    //fails to compile, because the capture of ? is not sufficiently narrow 
    private A<?> a; 

    public <T extends A<T>> setA(T a) { 
     this.a = a; 
    } 
} 

- ENDE DER FRAGE -

ich eine Tendenz, aus einer Anzahl von Mitgliedern Stackoverflow bemerkt haben bestimmte schwierige Fragen zu nähern mit „warum bist du das überhaupt machen? " Das Folgende ist eine Rechtfertigung meiner Verwendung dieses Musters - Sie können feststellen, dass die Java-Standardbibliothek in ihrer Definition der Enum-Klasse auch rekursive Selbsttypen verwendet: Enum<E extends Enum<E>>. Diese Frage in ähnlicher Weise aufgefordert werden könnte, wie „wie ein Feld vom Typ Enum<?> zu definieren

Begründung. Beispiel:

abstract class A<T extends A<T>> { 
    public abtract T self(); 
    public B<T> bify(Bifyer bifyer) { 
     return bifyer.bify(self()); 
    } 
} 

mit den Unterklassen:

class ASub1 extends A<ASub1> { 
    public ASub1 self() { return this; } 
}  

class ASub2 extends A<ASub2> { 
    public ASub2 self() { return this; } 
}  

zu einer parallelen Klassenhierarchie gebunden:

abstract class B<T extends A<T>> { 
} 

class BSub1<T extends A<T>> implements B<T> { } 
class BSub2<T extends A<T>> implements B<T> { } 
//and others 

Und mit der Generierung von B-Instanzen von implemen verwaltet tationen eine Bifyer Schnittstelle:

interface Bifyer { 
    B<ASub1> bify(ASub1 asub1); 
    B<ASub2> bify(ASub2 asub2);   
} 

Implementierungen dieser Schnittstelle im Wesentlichen eine Anwendung der Besucher-Muster Dies ist einen BSub1 oder BSub2 für die B zurückkehren, wo die Bifyer der Besucher ist, aber im Gegensatz zu den Standard-Besuchern die akzeptieren Methode gibt einen Wert anstelle von void zurück. Dies stellt ein modulares Framework zur Verfügung, in dem verschiedene Bifyer-Implementierungen angegeben werden können, um alternative Verhaltens- und Rückgabetypen für die Bify-Methode zu liefern - beispielsweise für jede Unterklasse von B.

+0

Es gibt keinen Grund, die Schranke zu verwenden ' erstreckt>' statt nur '' newacct

Antwort

4

Wenn Sie den Platzhalter ? unten durch A begrenzen, sollte es funktionieren:

public class B { 
    private A<? extends A> a; 

    public <T extends A<T>> void setA(T a) { 
     this.a = a; 
    } 
} 
+0

Ah, danke! Ich hatte versucht A > aber und andere Permutationen, aber diese war mir nicht eingefallen! –