Las enumeraciones no solo tienen que representar conjuntos pasivos (por ejemplo, colores). Pueden representar objetos más complejos con funcionalidad y, por lo tanto, es probable que desee agregar más funcionalidad a estos, por ejemplo, puede tener interfaces como Printable, Reportableetc. y componentes que los admitan.
Aquí hay un ejemplo (uno similar / mejor se encuentra en Effective Java 2nd Edition):
publicinterfaceOperator{int apply (int a,int b);}publicenumSimpleOperatorsimplementsOperator{
PLUS {int apply(int a,int b){return a + b;}},
MINUS {int apply(int a,int b){return a - b;}};}publicenumComplexOperatorsimplementsOperator{// can't think of an example right now :-/}
Ahora para obtener una lista de los operadores simples + complejos:
Los operadores complejos pueden ser "pow" y similares.
Pimgd
2
La primera vez que veo esa sintaxis de Enum (con las llaves después de los miembros), y he estado programando con Java durante 6 años. TIL
jrahhali
23
El Comparableejemplo dado por varias personas aquí es incorrecto, ya que Enumya lo implementa. Ni siquiera puedes anularlo.
Un mejor ejemplo es tener una interfaz que defina, digamos, un tipo de datos. Puede tener una enumeración para implementar los tipos simples y tener clases normales para implementar tipos complicados:
interfaceDataType{// methods here}enumSimpleDataTypeimplementsDataType{
INTEGER, STRING;// implement methods}classIdentifierDataTypeimplementsDataType{// implement interface and maybe add more specific methods}
Si, raro !! Enum ya implementa la interfaz comparable y no permite anular. Busqué el código fuente de Java para la clase enum y no pude encontrar la implementación compareTo. ¿Alguien puede decirme qué se compara dentro de un método compareTo un ENUM?
AKh
2
@AKh compara los ordinales, lo que significa que el orden natural es el orden de las constantes enum en el archivo fuente.
Jorn
Los enum vars son finales y, por lo tanto, la comparación ocurre con ==, ¿verdad?
djangofan
@djangofan sí.
Jorn
17
Hay un caso que uso a menudo. Tengo una IdUtilclase con métodos estáticos para trabajar con objetos implementando una Identifiableinterfaz muy simple :
publicinterfaceIdentifiable<K>{
K getId();}publicabstractclassIdUtil{publicstatic<T extendsEnum<T>&Identifiable<S>, S> T get(Class<T> type, S id){for(T t : type.getEnumConstants()){if(Util.equals(t.getId(), id)){return t;}}returnnull;}publicstatic<T extendsEnum<T>&Identifiable<S>, S extendsComparable<?super S>>List<T> getLower(T en){List<T> list =newArrayList<>();for(T t : en.getDeclaringClass().getEnumConstants()){if(t.getId().compareTo(en.getId())<0){
list.add(t);}}return list;}}
Dado que Enums puede implementar interfaces, se pueden usar para aplicar estrictamente el patrón singleton. Intentar hacer de una clase estándar un singleton permite ...
para la posibilidad de usar técnicas de reflexión para exponer métodos privados como públicos
para heredar de su singleton y anular los métodos de su singleton con otra cosa
Las enumeraciones como singletons ayudan a prevenir estos problemas de seguridad. Esta podría haber sido una de las razones contribuyentes para permitir que Enums actúe como clases e implemente interfaces. Solo una suposición.
for inheriting from your singleton and overriding your singleton's methods with something else. puedes usar un final classpara evitar eso
Dylanthepiguy
10
Es necesario para la extensibilidad: si alguien usa una API que ha desarrollado, las enumeraciones que defina son estáticas; no se pueden agregar ni modificar. Sin embargo, si deja que implemente una interfaz, la persona que usa la API puede desarrollar su propia enumeración usando la misma interfaz. Luego puede registrar esta enumeración con un administrador de enumeraciones que conglomera las enumeraciones junto con la interfaz estándar.
Editar: @Helper Method tiene el ejemplo perfecto de esto. Piense en tener otras bibliotecas que definan nuevos operadores y luego decirle a una clase de administrador que 'oye, esta enumeración existe, regístrala'. De lo contrario, solo sería capaz de definir Operadores en su propio código; no habría extensibilidad.
Las enumeraciones son solo clases disfrazadas, por lo que, en su mayor parte, todo lo que puede hacer con una clase puede hacerlo con una enumeración.
No puedo pensar en una razón por la cual una enumeración no debería poder implementar una interfaz, al mismo tiempo, tampoco puedo pensar en una buena razón para que lo hagan.
Yo diría que una vez que comience a agregar cosas como interfaces o métodos a una enumeración, debería considerar convertirla en una clase. Por supuesto, estoy seguro de que hay casos válidos para hacer cosas de enumeración no tradicionales, y dado que el límite sería artificial, estoy a favor de dejar que las personas hagan lo que quieran allí.
"... así que, en su mayor parte, todo lo que puedes hacer con una clase lo puedes hacer con una enumeración", sin embargo, no puedo decir que mi enumeración herede de una clase abstracta. Así que sí, énfasis en "en su mayor parte".
Adam Parkin el
55
Esto se debe a que todas las enumeraciones extienden java.lang.Enum, y las clases Java solo pueden extenderse desde una clase.
TofuBeer
6
Por ejemplo, si tiene una enumeración Logger. Entonces debe tener los métodos de registro como la depuración, información, advertencia y error en la interfaz. Hace que su código esté débilmente acoplado.
El uso más común para esto sería fusionar los valores de dos enumeraciones en un grupo y tratarlos de manera similar. Por ejemplo, vea cómo unir Frutas y Verduras .
Uno de los mejores casos de uso para que yo use enum con interfaz es Filtros de predicados. Es una forma muy elegante de remediar la falta de tipicidad de las colecciones de apache (si no se pueden usar otras bibliotecas).
La publicación anterior que mencionó las estrategias no enfatizó lo suficiente lo que una buena implementación liviana del patrón de estrategia usando enumeraciones le brinda:
publicenumStrategy{
A {@Overridevoid execute(){System.out.print("Executing strategy A");}},
B {@Overridevoid execute(){System.out.print("Executing strategy B");}};abstractvoid execute();}
Puede tener todas sus estrategias en un lugar sin necesidad de una unidad de compilación separada para cada una. Obtiene un buen envío dinámico solo con:
Strategy.valueOf("A").execute();
¡Hace que Java se lea casi como un lenguaje agradable escrito a máquina!
Las enumeraciones son como las clases de Java, pueden tener constructores, métodos, etc. Lo único que no puede hacer con ellas es new EnumName(). Las instancias están predefinidas en su declaración de enumeración.
¿Qué hay de enum Foo extends SomeOtherClass? Entonces, no es lo mismo que una clase regular, de hecho, es bastante diferente.
Adam Parkin el
@ Adam: Diría que las formas en que Enums se parecen a las clases son mucho más numerosas que las formas en que difieren de las clases. Pero no, no son idénticos.
scottb
Si descompila una enumeración, verá que es una clase que extiende la enumeración y tiene las "constantes" ya instanciadas en los campos de constructor / inicialización.
Cosmin Cosmin
3
Otra posibilidad:
publicenumConditionsToBeSatisfiedimplementsPredicate<Number>{
IS_NOT_NULL(Objects::nonNull,"Item is null"),
IS_NOT_AN_INTEGER(item -> item instanceofInteger,"Item is not an integer"),
IS_POSITIVE(item -> item instanceofInteger&&(Integer) item >0,"Item is negative");privatefinalPredicate<Number> predicate;privatefinalString notSatisfiedLogMessage;ConditionsToBeSatisfied(finalPredicate<Number> predicate,finalString notSatisfiedLogMessage){this.predicate = predicate;this.notSatisfiedLogMessage = notSatisfiedLogMessage;}@Overridepublicboolean test(finalNumber item){finalboolean isNotValid = predicate.negate().test(item);if(isNotValid){
log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);}return predicate.test(item);}}
y usando:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
Al crear constantes en un archivo jar, a menudo es útil permitir que los usuarios extiendan los valores de enumeración. ¡Usamos enumeraciones para las claves de PropertyFile y nos atascamos porque nadie podía agregar ninguna nueva! A continuación habría funcionado mucho mejor.
He rellenado un JavaFX ComboBox con los valores de una enumeración. Tengo una interfaz, Identificable (que especifica un método: identificación), que me permite especificar cómo se identifica cualquier objeto en mi aplicación con fines de búsqueda. Esta interfaz me permite escanear listas de cualquier tipo de objeto (cualquier campo que el objeto pueda usar para identidad) para una coincidencia de identidad.
Me gustaría encontrar una coincidencia para un valor de identidad en mi lista de ComboBox. Para utilizar esta capacidad en mi ComboBox que contiene los valores de Enum, debo poder implementar la interfaz identificable en mi Enum (que, como sucede, es trivial de implementar en el caso de un Enum).
Usé una enumeración interna en una interfaz que describe una estrategia para mantener el control de la instancia (cada estrategia es un Singleton) a partir de ahí.
publicinterfaceVectorizeStrategy{/**
* Keep instance control from here.
*
* Concrete classes constructors should be package private.
*/enumConcreteStrategyimplementsVectorizeStrategy{
DEFAULT (newVectorizeImpl());privatefinalVectorizeStrategy INSTANCE;ConcreteStrategy(VectorizeStrategy concreteStrategy){
INSTANCE = concreteStrategy;}@OverridepublicVectorImageGridIntersections processImage(MarvinImage img){return INSTANCE.processImage(img);}}/**
* Should perform edge Detection in order to have lines, that can be vectorized.
*
* @param img An Image suitable for edge detection.
*
* @return the VectorImageGridIntersections representing img's vectors
* intersections with the grids.
*/VectorImageGridIntersections processImage(MarvinImage img);}
El hecho de que el enum implemente la estrategia es conveniente para permitir que la clase enum actúe como proxy de su instancia adjunta. que también implementa la interfaz.
es una especie de estrategia EnumProxy: P el código clent se ve así:
Respuestas:
Las enumeraciones no solo tienen que representar conjuntos pasivos (por ejemplo, colores). Pueden representar objetos más complejos con funcionalidad y, por lo tanto, es probable que desee agregar más funcionalidad a estos, por ejemplo, puede tener interfaces como
Printable
,Reportable
etc. y componentes que los admitan.fuente
Aquí hay un ejemplo (uno similar / mejor se encuentra en Effective Java 2nd Edition):
Ahora para obtener una lista de los operadores simples + complejos:
Entonces, aquí usa una interfaz para simular enumeraciones extensibles (lo que no sería posible sin usar una interfaz).
fuente
El
Comparable
ejemplo dado por varias personas aquí es incorrecto, ya queEnum
ya lo implementa. Ni siquiera puedes anularlo.Un mejor ejemplo es tener una interfaz que defina, digamos, un tipo de datos. Puede tener una enumeración para implementar los tipos simples y tener clases normales para implementar tipos complicados:
fuente
Hay un caso que uso a menudo. Tengo una
IdUtil
clase con métodos estáticos para trabajar con objetos implementando unaIdentifiable
interfaz muy simple :Si creo un
Identifiable
enum
:Entonces puedo obtenerlo de
id
esta manera:fuente
Dado que Enums puede implementar interfaces, se pueden usar para aplicar estrictamente el patrón singleton. Intentar hacer de una clase estándar un singleton permite ...
Las enumeraciones como singletons ayudan a prevenir estos problemas de seguridad. Esta podría haber sido una de las razones contribuyentes para permitir que Enums actúe como clases e implemente interfaces. Solo una suposición.
Vea /programming/427902/java-enum-singleton y la clase Singleton en java para más discusión.
fuente
for inheriting from your singleton and overriding your singleton's methods with something else
. puedes usar unfinal class
para evitar esoEs necesario para la extensibilidad: si alguien usa una API que ha desarrollado, las enumeraciones que defina son estáticas; no se pueden agregar ni modificar. Sin embargo, si deja que implemente una interfaz, la persona que usa la API puede desarrollar su propia enumeración usando la misma interfaz. Luego puede registrar esta enumeración con un administrador de enumeraciones que conglomera las enumeraciones junto con la interfaz estándar.
Editar: @Helper Method tiene el ejemplo perfecto de esto. Piense en tener otras bibliotecas que definan nuevos operadores y luego decirle a una clase de administrador que 'oye, esta enumeración existe, regístrala'. De lo contrario, solo sería capaz de definir Operadores en su propio código; no habría extensibilidad.
fuente
Las enumeraciones son solo clases disfrazadas, por lo que, en su mayor parte, todo lo que puede hacer con una clase puede hacerlo con una enumeración.
No puedo pensar en una razón por la cual una enumeración no debería poder implementar una interfaz, al mismo tiempo, tampoco puedo pensar en una buena razón para que lo hagan.
Yo diría que una vez que comience a agregar cosas como interfaces o métodos a una enumeración, debería considerar convertirla en una clase. Por supuesto, estoy seguro de que hay casos válidos para hacer cosas de enumeración no tradicionales, y dado que el límite sería artificial, estoy a favor de dejar que las personas hagan lo que quieran allí.
fuente
Por ejemplo, si tiene una enumeración Logger. Entonces debe tener los métodos de registro como la depuración, información, advertencia y error en la interfaz. Hace que su código esté débilmente acoplado.
fuente
El uso más común para esto sería fusionar los valores de dos enumeraciones en un grupo y tratarlos de manera similar. Por ejemplo, vea cómo unir Frutas y Verduras .
fuente
Uno de los mejores casos de uso para que yo use enum con interfaz es Filtros de predicados. Es una forma muy elegante de remediar la falta de tipicidad de las colecciones de apache (si no se pueden usar otras bibliotecas).
fuente
La publicación anterior que mencionó las estrategias no enfatizó lo suficiente lo que una buena implementación liviana del patrón de estrategia usando enumeraciones le brinda:
Puede tener todas sus estrategias en un lugar sin necesidad de una unidad de compilación separada para cada una. Obtiene un buen envío dinámico solo con:
¡Hace que Java se lea casi como un lenguaje agradable escrito a máquina!
fuente
Las enumeraciones son como las clases de Java, pueden tener constructores, métodos, etc. Lo único que no puede hacer con ellas es
new EnumName()
. Las instancias están predefinidas en su declaración de enumeración.fuente
enum Foo extends SomeOtherClass
? Entonces, no es lo mismo que una clase regular, de hecho, es bastante diferente.Otra posibilidad:
y usando:
fuente
Al crear constantes en un archivo jar, a menudo es útil permitir que los usuarios extiendan los valores de enumeración. ¡Usamos enumeraciones para las claves de PropertyFile y nos atascamos porque nadie podía agregar ninguna nueva! A continuación habría funcionado mucho mejor.
Dado:
y:
uno podría tener una enumeración en el frasco:
y un usuario podría extenderlo para agregar sus propios colores:
fuente
Aquí está mi razón por la cual ...
He rellenado un JavaFX ComboBox con los valores de una enumeración. Tengo una interfaz, Identificable (que especifica un método: identificación), que me permite especificar cómo se identifica cualquier objeto en mi aplicación con fines de búsqueda. Esta interfaz me permite escanear listas de cualquier tipo de objeto (cualquier campo que el objeto pueda usar para identidad) para una coincidencia de identidad.
Me gustaría encontrar una coincidencia para un valor de identidad en mi lista de ComboBox. Para utilizar esta capacidad en mi ComboBox que contiene los valores de Enum, debo poder implementar la interfaz identificable en mi Enum (que, como sucede, es trivial de implementar en el caso de un Enum).
fuente
Usé una enumeración interna en una interfaz que describe una estrategia para mantener el control de la instancia (cada estrategia es un Singleton) a partir de ahí.
El hecho de que el enum implemente la estrategia es conveniente para permitir que la clase enum actúe como proxy de su instancia adjunta. que también implementa la interfaz.
es una especie de estrategia EnumProxy: P el código clent se ve así:
Si no implementara la interfaz hubiera sido:
fuente