As enums não precisam apenas representar conjuntos passivos (por exemplo, cores). Eles podem representar objetos mais complexos com funcionalidade e, portanto, é provável que você queira adicionar mais funcionalidades a eles - por exemplo, você pode ter interfaces como Printable, Reportableetc. , e componentes que os suportem.
Aqui está um exemplo (um similar / melhor é encontrado no 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 :-/}
Agora, para obter uma lista dos dois operadores simples e complexos:
Operadores complexos podem ser "preguiçosos" e similares.
Pimgd
2
É a primeira vez que vejo a sintaxe do Enum (com os chavetas depois dos membros), e estou programando com Java há 6 anos. TIL.
precisa saber é o seguinte
23
O Comparableexemplo dado por várias pessoas aqui está errado, pois Enumjá o implementa. Você nem pode substituí-lo.
Um exemplo melhor é ter uma interface que define, digamos, um tipo de dados. Você pode ter uma enumeração para implementar os tipos simples e ter classes normais para implementar tipos complicados:
interfaceDataType{// methods here}enumSimpleDataTypeimplementsDataType{
INTEGER, STRING;// implement methods}classIdentifierDataTypeimplementsDataType{// implement interface and maybe add more specific methods}
Sim. Estranho !!. O Enum já implementa a interface Comparable e não permite substituir. Procurei o código-fonte java para a classe enum e não consegui encontrar a implementação compareTo. Alguém pode me dizer o que é comparado dentro de um método compareTo um ENUM?
AKh
2
@AKh compara os ordinais, o que significa que a ordem natural é a ordem em que as constantes enum estão no arquivo de origem.
Jorn
Vars enum são finais e, portanto, a comparação ocorre com ==, certo?
djangofan
@djangofan yes.
Jorn
17
Há um caso que eu frequentemente uso. Eu tenho uma IdUtilclasse com métodos estáticos para trabalhar com objetos implementando uma Identifiableinterface muito simples :
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;}}
Como os Enums podem implementar interfaces, eles podem ser usados para impor rigorosamente o padrão singleton. Tentando fazer uma classe padrão um singleton permite ...
pela possibilidade de usar técnicas de reflexão para expor métodos privados como
por herdar do seu singleton e substituir os métodos do seu singleton por outra coisa
Enums como singletons ajudam a evitar esses problemas de segurança. Esse pode ter sido um dos motivos que contribuíram para permitir que o Enums atue como classes e implemente interfaces. Apenas um palpite.
for inheriting from your singleton and overriding your singleton's methods with something else. você pode simplesmente usar um final classpara evitar que
Dylanthepiguy
10
É necessário extensibilidade - se alguém usa uma API que você desenvolveu, as enumerações que você define são estáticas; eles não podem ser adicionados ou modificados. No entanto, se você permitir implementar uma interface, a pessoa que usa a API pode desenvolver sua própria enumeração usando a mesma interface. Em seguida, você pode registrar essa enumeração com um gerenciador de enumerações que conglomera as enumerações junto com a interface padrão.
Edit: @Helper Method tem o exemplo perfeito disso. Pense em ter outras bibliotecas definindo novos operadores e depois dizendo a uma classe gerenciadora que 'ei, essa enum existe - registre-a'. Caso contrário, você só poderá definir Operadores em seu próprio código - não haverá extensibilidade.
Enums são apenas classes disfarçadas; portanto, na maior parte do tempo, qualquer coisa que você possa fazer com uma classe pode fazer com uma enumeração.
Não consigo pensar em uma razão para que um enum não consiga implementar uma interface, ao mesmo tempo não consigo pensar em uma boa razão para isso.
Eu diria que, quando você começar a adicionar coisas como interfaces ou método a uma enumeração, considere realmente torná-la uma classe. É claro que tenho certeza de que existem casos válidos para fazer enum não tradicionais e, como o limite seria artificial, sou a favor de deixar as pessoas fazerem o que querem lá.
"... então, na maior parte do tempo, qualquer coisa que você possa fazer com uma classe, você pode fazer com uma enumeração", mas não posso dizer que minha enumeração seja herdada de uma classe abstrata. Então sim, ênfase em "na maior parte".
23613 Adam Parkin
5
Isso ocorre porque todas as enums estendem java.lang.Enum e as classes Java podem se estender apenas de uma classe.
TofuBeer
6
Por exemplo, se você tiver uma enumeração do Logger. Então você deve ter os métodos do logger, como depuração, informações, aviso e erro na interface. Isso torna seu código fracamente acoplado.
O uso mais comum para isso seria mesclar os valores de duas enums em um grupo e tratá-los da mesma forma. Por exemplo, veja como ingressar no Fruits and Vegatables .
Um dos melhores casos de uso para eu usar enum's com interface são os filtros de predicado. É uma maneira muito elegante de corrigir a falta de tipicidade das coleções apache (se outras bibliotecas não puderem ser usadas).
A publicação acima mencionada estratégias não enfatizou o suficiente o que uma implementação leve e agradável do padrão de estratégia usando enumeras faz com que você:
publicenumStrategy{
A {@Overridevoid execute(){System.out.print("Executing strategy A");}},
B {@Overridevoid execute(){System.out.print("Executing strategy B");}};abstractvoid execute();}
Você pode ter todas as suas estratégias em um só lugar sem precisar de uma unidade de compilação separada para cada uma. Você recebe um bom envio dinâmico apenas com:
Strategy.valueOf("A").execute();
Faz com que o Java seja lido quase como uma linguagem agradável e tipicamente digitada!
As enums são como classes Java, elas podem ter construtores, métodos etc. A única coisa que você não pode fazer com elas é new EnumName(). As instâncias são predefinidas na sua declaração enum.
Que tal enum Foo extends SomeOtherClass? Portanto, não é exatamente a mesma coisa que uma aula regular, de fato, bem diferente.
23613 Adam Parkin
@ Adam: Eu diria que as maneiras pelas quais as Enums se assemelham às classes são muito mais numerosas do que as maneiras pelas quais elas diferem das classes. Mas não, eles não são idênticos.
scottb
se você descompilar um enum, verá que é uma classe que estende a enumeração e tem as "constantes" já instanciadas nos campos de construtor / inicialização.
Cosmin Cosmin
3
Outra possibilidade:
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);}}
e usando:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
Ao criar constantes em um arquivo jar, geralmente é útil permitir que os usuários estendam valores de enumeração. Usamos enumerações para chaves PropertyFile e ficamos paralisadas porque ninguém poderia adicionar novas! Abaixo teria funcionado muito melhor.
Eu preenchi uma JavaFX ComboBox com os valores de um Enum. Eu tenho uma interface, identificável (especificando um método: identificar), que permite especificar como qualquer objeto se identifica para o meu aplicativo para fins de pesquisa. Essa interface permite verificar listas de qualquer tipo de objetos (qualquer que seja o campo que o objeto possa usar para identidade) para uma correspondência de identidade.
Gostaria de encontrar uma correspondência para um valor de identidade na minha lista ComboBox. Para usar esse recurso no meu ComboBox que contém os valores de Enum, devo poder implementar a interface Identificável no meu Enum (que, por acaso, é trivial de implementar no caso de um Enum).
Eu usei um enum interno em uma interface que descreve uma estratégia para manter o controle da instância (cada estratégia é um Singleton) a partir daí.
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);}
O fato de o enum implementar a estratégia é conveniente para permitir que a classe enum atue como proxy para sua Instância fechada. que também implementa a interface.
é um tipo de strategyEnumProxy: P o código clent se parece com isso:
Respostas:
As enums não precisam apenas representar conjuntos passivos (por exemplo, cores). Eles podem representar objetos mais complexos com funcionalidade e, portanto, é provável que você queira adicionar mais funcionalidades a eles - por exemplo, você pode ter interfaces como
Printable
,Reportable
etc. , e componentes que os suportem.fonte
Aqui está um exemplo (um similar / melhor é encontrado no Effective Java 2nd Edition):
Agora, para obter uma lista dos dois operadores simples e complexos:
Então, aqui você usa uma interface para simular enums extensíveis (o que não seria possível sem o uso de uma interface).
fonte
O
Comparable
exemplo dado por várias pessoas aqui está errado, poisEnum
já o implementa. Você nem pode substituí-lo.Um exemplo melhor é ter uma interface que define, digamos, um tipo de dados. Você pode ter uma enumeração para implementar os tipos simples e ter classes normais para implementar tipos complicados:
fonte
Há um caso que eu frequentemente uso. Eu tenho uma
IdUtil
classe com métodos estáticos para trabalhar com objetos implementando umaIdentifiable
interface muito simples :Se eu criar um
Identifiable
enum
:Então eu posso obtê-lo
id
desta forma:fonte
Como os Enums podem implementar interfaces, eles podem ser usados para impor rigorosamente o padrão singleton. Tentando fazer uma classe padrão um singleton permite ...
Enums como singletons ajudam a evitar esses problemas de segurança. Esse pode ter sido um dos motivos que contribuíram para permitir que o Enums atue como classes e implemente interfaces. Apenas um palpite.
Consulte /programming/427902/java-enum-singleton e a classe Singleton em java para obter mais discussão.
fonte
for inheriting from your singleton and overriding your singleton's methods with something else
. você pode simplesmente usar umfinal class
para evitar queÉ necessário extensibilidade - se alguém usa uma API que você desenvolveu, as enumerações que você define são estáticas; eles não podem ser adicionados ou modificados. No entanto, se você permitir implementar uma interface, a pessoa que usa a API pode desenvolver sua própria enumeração usando a mesma interface. Em seguida, você pode registrar essa enumeração com um gerenciador de enumerações que conglomera as enumerações junto com a interface padrão.
Edit: @Helper Method tem o exemplo perfeito disso. Pense em ter outras bibliotecas definindo novos operadores e depois dizendo a uma classe gerenciadora que 'ei, essa enum existe - registre-a'. Caso contrário, você só poderá definir Operadores em seu próprio código - não haverá extensibilidade.
fonte
Enums são apenas classes disfarçadas; portanto, na maior parte do tempo, qualquer coisa que você possa fazer com uma classe pode fazer com uma enumeração.
Não consigo pensar em uma razão para que um enum não consiga implementar uma interface, ao mesmo tempo não consigo pensar em uma boa razão para isso.
Eu diria que, quando você começar a adicionar coisas como interfaces ou método a uma enumeração, considere realmente torná-la uma classe. É claro que tenho certeza de que existem casos válidos para fazer enum não tradicionais e, como o limite seria artificial, sou a favor de deixar as pessoas fazerem o que querem lá.
fonte
Por exemplo, se você tiver uma enumeração do Logger. Então você deve ter os métodos do logger, como depuração, informações, aviso e erro na interface. Isso torna seu código fracamente acoplado.
fonte
O uso mais comum para isso seria mesclar os valores de duas enums em um grupo e tratá-los da mesma forma. Por exemplo, veja como ingressar no Fruits and Vegatables .
fonte
Um dos melhores casos de uso para eu usar enum's com interface são os filtros de predicado. É uma maneira muito elegante de corrigir a falta de tipicidade das coleções apache (se outras bibliotecas não puderem ser usadas).
fonte
A publicação acima mencionada estratégias não enfatizou o suficiente o que uma implementação leve e agradável do padrão de estratégia usando enumeras faz com que você:
Você pode ter todas as suas estratégias em um só lugar sem precisar de uma unidade de compilação separada para cada uma. Você recebe um bom envio dinâmico apenas com:
Faz com que o Java seja lido quase como uma linguagem agradável e tipicamente digitada!
fonte
As enums são como classes Java, elas podem ter construtores, métodos etc. A única coisa que você não pode fazer com elas é
new EnumName()
. As instâncias são predefinidas na sua declaração enum.fonte
enum Foo extends SomeOtherClass
? Portanto, não é exatamente a mesma coisa que uma aula regular, de fato, bem diferente.Outra possibilidade:
e usando:
fonte
Ao criar constantes em um arquivo jar, geralmente é útil permitir que os usuários estendam valores de enumeração. Usamos enumerações para chaves PropertyFile e ficamos paralisadas porque ninguém poderia adicionar novas! Abaixo teria funcionado muito melhor.
Dado:
e:
alguém poderia ter um enum no pote:
e um usuário pode estendê-lo para adicionar suas próprias cores:
fonte
Aqui está a minha razão pela qual ...
Eu preenchi uma JavaFX ComboBox com os valores de um Enum. Eu tenho uma interface, identificável (especificando um método: identificar), que permite especificar como qualquer objeto se identifica para o meu aplicativo para fins de pesquisa. Essa interface permite verificar listas de qualquer tipo de objetos (qualquer que seja o campo que o objeto possa usar para identidade) para uma correspondência de identidade.
Gostaria de encontrar uma correspondência para um valor de identidade na minha lista ComboBox. Para usar esse recurso no meu ComboBox que contém os valores de Enum, devo poder implementar a interface Identificável no meu Enum (que, por acaso, é trivial de implementar no caso de um Enum).
fonte
Eu usei um enum interno em uma interface que descreve uma estratégia para manter o controle da instância (cada estratégia é um Singleton) a partir daí.
O fato de o enum implementar a estratégia é conveniente para permitir que a classe enum atue como proxy para sua Instância fechada. que também implementa a interface.
é um tipo de strategyEnumProxy: P o código clent se parece com isso:
Se não implementasse a interface, teria sido:
fonte