2010-11-22 25 views
10

J'ai une classe générique qui représente un fragment de texte. Ce fragment de texte peut avoir un nombre de modes différents (différents types de mise en évidence). Ces modes sont représentés par un Enum. L'Enum pourrait être différent pour chaque projet mais il doit implémenter une interface qui fournit une méthode pour en combiner 2 (pourrait être surlignée et en gras). Donc, j'ai une interface:Génériques Java de génériques de

public interface TextFragmentMode<E extends Enum<E>> { 
    /** 
    * Will combine the supplied mode with the current mode and return the 
    * result. 
    * 
    * @param mode The mode to combine with. 
    * @return The combined mode. 
    */ 
    public E combine(E mode); 
} 

Alors mon TextFragment est un conteneur pour les deux une chaîne de texte et un mode. Mais quand j'essaie de déclarer la classe:

public class TextFragment<E extends TextFragmentMode<E extends Enum<E>>> { 
    StringBuilder text; 
    E mode; 
    ... 

Je reçois l'erreur suivante:

Syntax error on token "extends", , expected

qui, selon éclipser la coloration syntaxique, fait référence à la partie

E extends Enum<E> 

de le code. Est-ce que quelqu'un sait ce que je fais mal? Je dois manquer quelque chose sur les génériques ...

--------------------- modifier -------------- Je prends enfin le temps de lire Effective Java de Josh Bloch (deuxième édition), et il s'avère que cet exemple d'utilisation est Item 34: Emulate enums extensible avec les interfaces. Autant que je voudrais dire que le grand esprit pense de même ... Ce serait trop présomptueux!

+0

Thx je luttais si dur avec P :) – Snicolas

Répondre

12

TextFragment<E> doit dire deux choses à propos de E.

  • Il "s'étend" TextFragmentMode<E>. Pour ce faire, vous devez également le contraindre à étendre Enum<E>.

En raison de l'héritage Java wonkiness, vous avez besoin d'écrire que l'inverse:

public class TextFragment<E extends Enum<E> & TextFragmentMode<E>> { 
+0

Je dois essayer ça ... Je reviens à vous dessus ... – Lucas

+1

Oui, cela fonctionne. Merci beaucoup! Il s'avère son appelé un type d'intersection dans la 3ème édition de JLS. Cela aurait été bien si le tutoriel sur les génériques Java mentionnait même qu'il pourrait y avoir des scénarios d'utilisation plus avancés. Pour ceux qui trouvent cette question, il y a plus d'informations utiles ici: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html et ici: http://stackoverflow.com/questions/ 574529/coding-tip-intersection-types-et-java-enums Encore une fois, merci. – Lucas

6

Le problème est que vous essayez de faire E étendre TextFragmentModeetEnum, qui ne sont pas liés types. Quel type E répondrait aux deux contraintes?

Je suppose que vous voulez deux paramètres de type, quelque chose comme ceci:

public class TextFragment<E extends Enum<E>, M extends TextFragmentMode<E>> 

Maintenant que vous avez chaque contrainte exprimée sur un paramètre de type différent, et ils ont tous deux de sens - vous pouvez certainement trouver un E qui est un enum, et un M qui est un TextFragmentMode<E>. Cependant, il est assez compliqué ...

... vous certainement besoin d'être ce générique? Que ferez-vous avec M dans la classe? Ne pourriez-vous pas prendre un TextFragmentMode<E> en tant que paramètre constructeur (ou autre) et le rendre générique dans un paramètre de type?

+0

Ok, donc votre ligne de code résultat est un des solutions auxquelles je suis arrivé, mais ça rend tout moche. Ensuite, chaque fois que vous déclarez/instanciez vous avez besoin des deux paramètres de type et ils sont eux-mêmes un peu longs. Vous finissez par utiliser 80 caractères sur le nom du type. Et dans la pratique, mon type de mise en œuvre était: MyType public enum implémente TextFragmentMode qui est à la fois un ENUM et TextFragmentMode ... – Lucas

1

Vous devez introduire un nouveau type qui représente la limite de Enum

public class TextFragment<T extends Enum<T>, E extends TextFragmentMode<T>> { 
+0

Encore une fois (par commentaire ci-dessus) Je ne aime pas vraiment ce (bien qu'il travaillerait) à cause de l'inélégance. C'est très laid à regarder et il semble qu'il devrait y avoir une meilleure façon de le faire. – Lucas

-1

Sans test, je suppose:

public class TextFragment<E extends TextFragmentMode<E>> { 

Hmm, court test montre qu'il ne semble pas pour travailler soit ...

+0

Ne compile pas, car vous devez contraindre 'E extends Enum ', afin d'être compatible avec 'TextFragmentMode'. –