2011-06-08 24 views
22

Estoy usando una máquina de estado, y el código se vuelve realmente detallado cuando se prueba en una gran cantidad de estados posibles.¿Hay alguna forma de hacer bitwise-O enumeraciones en Java?

enum Mood { 
    HAPPY, SAD, CALM, SLEEPY, OPTIMISTIC, PENSIVE, ENERGETIC; 
} 

¿Hay alguna manera de hacer esto:

if (currentMood == (HAPPY | OPTIMISTIC | ENERGETIC) {} 

lugar de esto:

if (currentMood == HAPPY || currentMood == OPTIMISTIC || currentMood == ENERGETIC) {} 

O sería mejor quedarse con números enteros y banderas en este caso?

+6

Usted quiere decir 'if ((currentMood y (FELIZ | OPTIMISTIC | ENERGETIC))! = 0) {} '. O tal vez 'if (((1 << currentMood) & ((1 << HAPPY) | (1 << OPTIMISTIC) | (1 << ENERGETIC)))!! = 0) {}'. Supongo que estoy feliz de que lo hagas bien. –

+0

Deduzco de "enteros y banderas" que el actualMood puede ser más de un estado de ánimo. – blizpasta

+0

@Tom - Sí, técnicamente tiene razón. Estaba dividido entre escribir en operaciones bit a bit de estilo C o una sintaxis de tipo de teoría de conjuntos. –

Respuesta

32

Tal vez usar algo como EnumSet?

if (EnumSet<Mood>.of(HAPPY, OPTIMISTIC, ENERGETIC).contains(currentMood)) 
{ 
//Do stuff... 
} 
+3

Creo que incluso puede soltar el en este caso –

+1

Gracias, eso es lo que estaba buscando. IMO es mejor que el enfoque de cambio de caja porque es más conciso. –

3

switch(currentmood){ 
    case HAPPY: 
    case OPTIMISTIC:... 
     Then do this 
     break; 
    default://else 
} 
0

Cuando se utiliza || debe especificar ambos valores que está comparando cada vez. Sin embargo, podría escribir fácilmente un pequeño método para hacer esto.

if (currentMood.hasMood(HAPPY, OPTIMISTIC, ENERGETIC)) {} 

public boolean hasMood(Mood ....) 
11

Dale a tus enums un atributo int.

enum Mood { 
    private int id; 

    HAPPY(1), SAD(2), CALM(4), SLEEPY(8), OPTIMISTIC(16), PENSIVE(32), ENERGETIC(64); 

    Mood(int id) { 
     this.id = id; 
    } 
} 

En el caso, la prueba en contra de esta atrribuya.

if (currentMood & (HAPPY.id | OPTIMISTIC.id | ENERGETIC.id) != 0) { ... } 
+1

Si tiene confianza en el orden del código fuente (un "si" moderadamente grande) también puede usar el 'ordinal()'. – Darien

+0

No puede usar 'ordinal()' porque eso le daría '0',' 1', '2',' 3', etc., que no funcionarán con 'OR' de bit. – isapir

+0

Una respuesta un poco tardía, pero es probable que pueda hacer '1 << ordinal()' –

1

Puede dar a su enum una bandera booleana y probar para eso.

enum Mood { 
    HAPPY(true), SAD, CALM, SLEEPY, OPTIMISTIC(true), PENSIVE, ENERGETIC(true); 
    final boolean good; 

    Mood(){this(false);} 

    Mood(boolean isgood){this.good = isgood;} 

    public isGood(){return good;} 
} 

De esta manera el cheque es corto

if (currentMood.isGood()) {} 
0

Un enfoque es tener EnumSet/conmutador/Si etc. Esto tiene sentido si se está clasificando la enumeración de alguna manera que no es intrínsecamente parte de la enumeración misma. Por ejemplo, si un color es parte del color de la bandera nacional. El 'modelo de dependencia' es que la bandera nacional depende del Color, pero a Color no le importa la existencia de banderas nacionales.

Por otro lado, si está tratando de determinar si un color es un color primario o no (intrínseco al modelo humano de color), entonces pertenece a la clase enum. Así,

enum Color { 
    private final boolean _crtPrimary; 

    Red(true), Green(true), Blue(true), Black(false) 

    Color(boolean crtPrimary) { 
    _crtPrimary = crtPrimary; 
    } 

    public boolean isCRTPrimary() { 
    return _crtPrimary; 
    } 
} 
2

Aparte de otras respuestas: si ese conjunto particular de estados tiene un significado semántico definido en su aplicación (en lugar independiente de su método particular, específico para el Enum), me gustaría recomendar a esa prueba incluido como un método en la misma clase Enum.

enum Mood { 
    HAPPY, SAD... 

    public boolean isRatherPositive() { 
     .... 
    } 

} 

(o un método estático) a ser implementado por cualquiera de la lógica sugerida por las otras respuestas (Me favorecer la EnumSet, que podría ser estáticamente o con pereza instancia).

Tener el método en Enum es útil para evitar la duplicación de código, pero sobre todo, para evitar errores en caso de que agregue miembros al Enum o lo modifique.

1

Otra opción:

public enum PaymentResponse { 
    PP_SUCCESS, PP_FAILURE, CC_SUCCESS, CC_FAILURE; 

    public boolean isSuccessful() { 
      return ordinal() == CC_SUCCESS.ordinal() || 
        ordinal() == PP_SUCCESS.ordinal() ; 
    } 
} 
+0

por qué no simplemente 'devolver esto == CC_SUCCESS || esto == PP_SUCCESS; '? – Wulf

0

Usted puede utilizar YourEnum. valores()

Por ejemplo, tengo clase llamada enumeraciones. En él, tengo múltiples clases Enum.

Por ejemplo:

public class Enumerations { 

public enum smtg 
{ 
    Fast(1), 
    Slow(2); 

    private int number; 
    private smtg(final int num) { number = num; } 
    public int getsmtg() 
    { 
     return number; 
    } 
} 
...... 

}

Cuando quiero usar bit a bit, sólo lo utilizan como esa:

Enumerations.smtg.values()[Enumerations.smtg.Slow.ordinal() | Enumerations.smtg.Fast.ordinal()] 
Cuestiones relacionadas