2009-03-29 5 views
4

donné une hiérarchie de classes où la classe de base définit une auto-type récursif:Type de champ Java pour une valeur d'un self-type générique récursif?

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

Comment puis-je déclarer une autre classe (qui ne devrait pas être générique en T, car un tel T peut varier au cours de la durée de vie du objet) avec un champ pouvant contenir n'importe quelle sous-classe de A?

Ce qui suit ne fonctionne pas:

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; 
    } 
} 

- FIN DE QUESTION -

J'ai remarqué une tendance d'un certain nombre de membres StackOverflow d'aborder certaines questions difficiles avec « pourquoi êtes-vous faire cela en premier lieu? " Ce qui suit est une justification de mon utilisation de ce modèle - vous pouvez noter que la bibliothèque standard Java utilise également des auto-types récursifs dans sa définition de la classe Enum: Enum<E extends Enum<E>>. Cette question pourrait de même être posée « comment définir un champ de type Enum<?>

Justification exemple:.

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

avec les sous-classes:

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

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

lié à une hiérarchie de classes parallèles:

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 

Et avec génération d'instances B gérées par implemen tations d'une interface Bifyer:

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

Implémentations de cette interface peut renvoyer un BSub1 ou BSub2 pour B. Ceci est essentiellement une application du modèle des visiteurs où le Bifyer est le visiteur, mais contrairement à la norme visiteur l'accepter method renvoie une valeur au lieu de void. Cela fournit un cadre modulaire où différentes implémentations Bifyer peuvent être spécifiées pour fournir des types de comportement et de retour alternatifs pour la méthode Bify - disons un pour chaque sous-classe de B.

+0

Il n'y a aucune raison d'utiliser la borne '>' au lieu de simplement '' newacct

Répondre

4

Si vous avez lié le caractère générique ? ci-dessous par A, cela devrait fonctionner:

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

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

Ah, merci! J'avais tenté A > mais et d'autres permutations mais celui-ci ne m'était pas venu à l'esprit! –

Questions connexes