2009-07-01 7 views
39

Je ne suis pas convaincu à 100% que ce soit une bonne idée, mais je suis tombé sur un certain code aujourd'hui qui est actuellement mis en œuvre comme:Comment puis-je exiger qu'un paramètre générique soit une énumération qui implémente une interface?

class MyWidget <T extends Enum<T> > { 
    MyWidget(Map<T, Integer> valueMap) { 
    mValueMap = valueMap; 
    } 

    Map<T, Integer> mValueMap; 
} 

MyWidget offre alors des méthodes qui utilisent mValueMap pour convertir le passé en Enum vers/depuis un Integer.

Ce que je considérais faire était d'essayer de factoriser cela, de sorte que je déclare mon énumération:

interface MyInterface { 
    public Integer getValue(); 
} 

enum MyEnum implements MyInterface { 
    foo, bar; 
    public Integer getValue() { 
    return ordinal(); 
    } 
} 

Et je alors en mesure de réécrire MyWidget en quelque chose qui ressemblait vaguement à ceci:

public class MyWidget<T extends Enum<T> extends MyInterface> { 
    ... 
} 

et serait alors en mesure d'appeler la méthode getValue() de MyInterface sur T -type objets dans MyWidget. Le problème, bien sûr, est que "<T extends Enum<T> extends MyInterface>" n'est pas une syntaxe valide. Y a-t-il un moyen de retirer cela?

Je ne veux pas simplement avoir MyWidget<T extends MyInterface>, car il est également important que T soit une énumération.

Merci d'avance!

Répondre

77

Utilisez un '&' au lieu:

public class MyWidget<T extends Enum<T> & MyInterface> { 
    ... 
} 

Les appels JLS ce un "type d'intersection", mais je ne trouve aucune mention dans les tutoriels Java. Je vais juste dire qu'il fait exactement ce que vous souhaitiez que "extends" ferait.

En outre, je devrais mentionner que vous pouvez avoir autant de types que vous voulez dans le type d'intersection. Donc, si vous vouliez, vous pourriez faire:

public class MyWidget<T extends Enum<T> & MyInterface & Serializable & Cloneable> { 
    ... 
} 

[Note: cet exemple de code ne doit pas être interprété comme une approbation de l'interface Cloneable; il était simplement à portée de main au moment]

+0

La syntaxe & est soignée, mais je trouve que l'utiliser se transforme généralement en une odeur de code, et est une indication que quelque chose ne va pas tout à fait avec votre modèle. – skaffman

+2

J'ai tendance à être d'accord (je pense que je l'ai utilisé peut-être une ou deux fois, si cela). Mais dans le cas des enums implémentant une interface, je pense que c'est approprié. –

+0

Excellent! C'est exactement ce que je cherchais. Merci beaucoup! – Sbodd

1

La JSR 203 (nouvelle nouvelle IO) choses pour JDK 7 fait beaucoup d'utilisation des énumérations qui mettent en œuvre des interfaces (par exemple: http://openjdk.java.net/projects/nio/javadoc/java/nio/file/FileVisitOption.html). pour leur permettre une certaine marge de manœuvre dans l'avenir pour de futurs ensembles supplémentaires d'options enum. Donc, c'est une approche réalisable et évidemment celle qui a été choisie après beaucoup de réflexion dans un grand projet de Sun.

+0

Neat.J'espère que java 7 apparaîtra avant que ma barbe ne devienne grise. – skaffman

+0

De l'écriture d'une petite quantité de code qui utilise ce genre de choses, j'ai l'impression que c'est un peu bizarre. Je ne peux pas dire que je l'ai vu ailleurs. Quelque chose avec un 7 dans le nom sortira en 2010, je suis assez sûr. Je ne sais pas si ce sera "Java 7" tel qu'approuvé par le JCP. Seul Oracle peut répondre à cela maintenant ... –

Questions connexes