2012-08-10 16 views
7

Estoy tratando de tener una colección de enumeraciones que se extienden de una interfaz común, así que algo como:Enum <? se extiende la interfaz>

interface Fooable 
{ 
    void someCommonMethod(); 
} 

enum E1 implements Fooable 
{ 
    // some enumuerations and a definition for someCommonMethod() 
} 

enum E2 implements Fooable 
{ 
    // some different enumerations and a different definition for someCommonMethod() 
} 

y luego hacer uso de esto en otro lugar mediante la aplicación tanto de que una variable es una enumeración y implementa la interfaz. Así que algo en la línea de ..

bar(Enum<? extends Fooable> fe) 
{ 
    fe.ordinal(); 
    fe.someCommonMethod(); 
} 

Sin embargo, hasta ahora no parecen tener que echar Fe con el fin de tratarla como la implementación de la interfaz, es decir,

bar(Enum<? extends Fooable> fe) 
{ 
    fe.ordinal(); 
    ((Fooable)fe).someCommonMethod(); 
} 

y si bien esto debe ser seguro ... parece poco óptimo y que puedo estar pasando por alto algo. Por supuesto, si trato de pasar el param como un Fooable, entonces termino el casting para tratarlo como un Enum y no solo no es ganancia, ahora ni siquiera estoy seguro. Ver siguiente:

bar(Fooable fe) 
{ 
    // potentially unsafe cast! 
    ((Enum<?>)fe).ordinal(); 
    fe.someCommonMethod(); 
} 

¿Hay algo que estoy pasando por alto o es el

Enum<? extends Fooable> 

lo más cercano a una solución 'bueno' como voy a conseguir?

Soy relativamente nuevo en Java y todavía estoy tratando de usarlo como C o C++, así que si lo estoy tratando como un martillo en lugar de una sierra o pasando por alto algo estúpidamente simple, siéntase libre de señalarlo :)

Respuesta

1

Una opción que ha Ve es agregar cualquiera de los métodos de Enum que necesita a Fooable o crear una nueva interfaz que amplíe Fooable y agregue los métodos de Enum que necesita.

Ejemplo:

interface Fooable { 
    void someCommonMethod(); 
} 

interface FooableEnum extends Fooable { 
    int ordinal(); 
} 

enum E1 implements FooableEnum { 
    // Implement someCommonMethod. 
    // ordinal() is already implemented by default. 
} 

Una vez hecho esto, puedes usar FooableEnum como el tipo de parámetro en la firma del método y no preocuparse por ninguna de las cosas genéricas.

+0

Había pensado en esto, pero tenía reservas sobre su comportamiento con respecto a los valores(), puede valer la pena volver a visitarlo, aunque ahora mismo no soy capaz de extraer una reserva válida ... – Khanmots

+0

Esto requiere una interfaz innecesaria . –

+0

@Mike, más pienso en esto cuanto más pienso que es el camino correcto. Mi requisito no es realmente que el tipo ** es ** una enumeración, es que tiene el ** comportamiento ** de una enumeración. También me he convencido a mí mismo de que los valores() no van a ser un problema y que soy tonto. – Khanmots

18

Esto significa que T se extiende enumeración e implementa Fooable:

<T extends Enum<T> & Fooable> 

Así, su método se puede escribir como:

<T extends Enum<T> & Fooable> void bar(T fe) { 
    fe.ordinal(); 
    fe.someCommonMethod(); 
} 
+0

Sí, pero tengo entendido que solo se utiliza cuando se declara que un genérico no define un parámetro para un método. – Khanmots

+2

@Khanmots [Los métodos mismos pueden ser genéricos] (http://docs.oracle.com/javase/tutorial/extra/generics/methods.html). –

+0

No había pensado en ese enfoque ... había experimentado con la interfaz genérica con una T que se extiende Enum y Fooable , pero puede que tenga que dar vueltas haciendo que la clase adjunta sea genérica para que todos sus métodos puedan tener una T con ambas restricciones ... – Khanmots

Cuestiones relacionadas