2015-12-27 10 views
5

Ho un'interfaccia vuota Units che sto usando per etichettare diversi enums quindi so che contengono unità diverse (ad es. Ho uno enum TemperatureUnits implements Units{} che memorizza Fahrenheit, Celsius, ecc, quindi ho un DistanceUnits che tiene metri, piedi, eccGestione di valori di enum da enumerazioni diverse che implementano una determinata interfaccia in uno switch/caso

voglio fare cose diverse in uno switch/caso sulla base del quale enum valore viene passato a un metodo. voglio che accettare un valore da qualsiasi enum che implementa Units.Il problema è che, dal momento che le classi enums sono in realtà diverse, devo utilizzare il nome qualificato del valore nello switch/ca SE. Il mio codice simile a questa:

 public static void foo(Units units){ //units has to be an enum that implements Units 

     switch (units){ 
      case TemperatureUnits.FAHRENHEIT: //I can't say just FAHRENHEIT, because Units itself doesn't 
       //have a FAHRENHEIT value, but it won't let me say TemperatureUnits.FAHRENHEIT because it won't let use 
       // qualified enum values as cases. 
       //Do stuff 
       break; 
      case DistanceUnits.METERS: 
       //Do other stuff 
       break; 
      //...etc 

Come avrei un'istruzione switch/caso che può utilizzare valori diversi da enums?

Edit: La mia interfaccia Units è solo:

public interface Units{ 
    String getLabel(); 
} 
+3

utilizzare il polimorfismo al posto di un caso interruttore gigante, che sarebbe diventato non corretta al più presto una nuova costante enum o enum classe è definita. Aggiungi un metodo in Unità, sovrascrivilo in tutte le enumerazioni e chiamalo invece di eseguire il blocco switch. ad esempio, usa unit.foo() invece di foo (unità). L'interfaccia deve essere denominata "Unità", BTW: CELSIUS_DEGREE è un'unità, non un'unità. –

+1

Sembra una situazione in cui stai definendo una * classe tag *, cioè il comportamento della classe cambia in modo significativo a seconda del valore di qualche tag (Temperatura, Distanza, ecc.) In questo caso, il tuo migliore, il più elegante e la soluzione più solida (come menzionato da JB) è sviluppare una gerarchia di classi (ad esempio TemperatureUnits è una sottoclasse di Unità). Altrimenti, il tuo codice può sembrare molto brutto se provi a fare tutto con una grande classe (o enum). Il comportamento specifico desiderato può essere facilmente definito dalle sottoclassi. – scottb

+0

Perché vuoi avere un enum base per cose totalmente indipendenti come la temperatura, la distanza e così via? – Robert

risposta

0

È possibile utilizzare l'operatore instanceof per determinare quale enum è stata approvata in, & poi switch in base alla appropriata enum:

public static void foo(Units units) { 
    if(units instanceof DistanceUnits) { 
     DistanceUnits d = (DistanceUnits) units; // METERS, INCHES... 

     switch (d) { 
      case METERS: 
       // code 
       break; 
      case INCHES: 
       // code 
       break; 
     } 
    } 
    else if(units instanceof TemperatureUnits) { 
     TemperatureUnits t = (TemperatureUnits) units; // FAHRENHEIT, CELSIUS 

     switch (t) { 
      case FAHRENHEIT: 
       // code 
       break; 
      case CELSIUS: 
       // code 
       break; 
     } 
    } 
} 

Considerando this:

enum DistanceUnits implements Units { 
    METERS, INCHES 
} 

enum TemperatureUnits implements Units { 
    FAHRENHEIT, CELSIUS 
} 

public interface Units { 
    // some code 
} 
3

Ciò non è consentito dalle specifiche del linguaggio Java.

14.11. The switch Statement dice che

Il tipo di espressione deve essere char, byte, short, int, Carattere, Byte, Corto, Integer, String, o un tipo enum (§8.9), o un di compilazione si verifica un errore temporale.

Qui, il Espressione è il valore che si sta Accensione (switch(expression)). Nel tuo caso, il tipo dell'espressione è Units che è un'interfaccia e non uno enum.

successivo a tale etichetta

Ogni caso ha una cassa costante, che è o un'espressione costante o il nome di un costante enum.

Enum constants non sono qualificati dal tipo enum, quindi non è possibile mescolare diverse costanti di tipo enum in uno switch.

Una possibile soluzione per voi potrebbe essere quella di implementare in questo modo:

interface Unit { 
    void doSomething(); 
} 

enum A implements Unit { 
    A_ONE, 
    A_TWO, 
    A_THREE { 
     void doSomething() { 
      // implement it in a way specific for A_THREE 
     } 
    }; 

    void doSomething() { 
     // implement it in a generic way for A 
    } 
} 

In questo modo ogni enum che implementa Unit può - e deve - avere la "logica di movimentazione" incapsulata all'interno di esso e se avete qualsiasi costanti di enum speciali - possono implementare la logica speciale da sole. Naturalmente, a volte ogni costante enum può avere un'implementazione specifica e non ci sarà un generico a livello di classe enum.

1

Questo potrebbe soddisfare il vostro caso d'uso:

/** Defines all supported unit types */ 
public enum UnitType { 
    Distance, 
    Temperature, 
    Volume 
}; 

/** Defines all units (of all supported unit types) */ 
public enum Units { 

    FEET(UnitType.Distance), 
    METERS(UnitType.Distance), 

    FAHRENHEIT(UnitType.Temperature), 
    CELSIUS(UnitType.Temperature), 

    GALLONS(UnitType.Volume), 
    LITERS(UnitType.Volume); 

    private final UnitType type; 

    Units(UnitType type) { 
     this.type = type; 
    }; 

    public UnitType getType() { 
     return type; 
    } 

} 

// In some class 
... 
public static void foo(Units units) { 
    switch (units) { 
     case FAHRENHEIT: 
      // ... 
      break; 
     case METERS: 
      // ... 
      break; 
     case GALLONS: 
      // ... 
      break; 
     // ... 
    } 
} 
+0

Sembra che potrebbe funzionare. Lo proverò. – Caketray

+0

Hai dimenticato uno di questi '* /', btw – Caketray

+0

Grazie. Quel commento ora è finito. – cybersam