2015-12-27 14 views
5

Farklı enums etiketlerini kullanıyorum boş bir arabirim var Units Farklı birimlerde tuttuklarını biliyorum (örneğin, enum TemperatureUnits implements Units{} depolarım var) vb Fahrenheit, Celsius, o zaman ben metre, fit tutan bir DistanceUnits, var vs.Belirli bir arabirimi bir anahtar/vakada uygulayan farklı enumlarla işleme Enum değerleri

hangi enum değer bir yönteme geçirilen dayalı bir anahtar/durumunda farklı şeyler yapmak istiyorum

. Ben bunu istiyorum Units'u uygulayan herhangi bir enum'dan bir değeri kabul edin. Sorun şu ki, enums aslında farklı sınıflar olduğundan, anahtar/ca'daki değerin nitelikli adını kullanmalıyım se. Benim kod şöyle görünür:

 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 

farklı enums değerleri kullanabileceğiniz bir switch/case deyimi olurdu nasıl?

Düzenleme: Benim Units arayüzü adildir:

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

Kullanım polimorfizm, bu kadar kısa sürede yeni enum sabiti veya enum sınıfı tanımlanmıştır olarak yanlış olacaktı. Birimler'e bir yöntem ekleyin, tüm numaralarda geçersiz kılın ve anahtar bloğunu yürütmek yerine onu çağır. foo (birimler) yerine units.foo() kullanın. Arayüz "Unit", BTW olarak adlandırılmalıdır: CELSIUS_DEGREE bir Birim, Bir Birim değil. –

+1

Bu, * etiketli bir sınıfı tanımladığınız bir duruma benziyor *, yani sınıfın davranışı, önemli ölçüde bazı etiketlerin değerine bağlı olarak değişir (Sıcaklık, Mesafe, vb.). Bu durumda, en iyi, en şıkınız ve en sağlam çözüm (JB'nin bahsettiği gibi) bir sınıf hiyerarşisi geliştirmektir (örn. TemperatureUnits, Birimlerin alt sınıfıdır). Aksi halde, kodunuz çok büyük bir sınıf (veya enum) ile yapmaya çalışırsanız çok çirkin görünebilir. İstediğiniz özel davranış alt sınıflar tarafından kolayca tanımlanabilir. – scottb

+0

Niçin sıcaklık, mesafe ve benzeri gibi tamamen ilgisiz şeyler için bir temel enum'a sahip olmak istersiniz? – Robert

cevap

0

Sen enum geçirildi belirlemek için instanceof operatörünü kullanabilirsiniz, & sonra enum uygun dayalı switch: düşünüldüğünde

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; 
     } 
    } 
} 

bu:

enum DistanceUnits implements Units { 
    METERS, INCHES 
} 

enum TemperatureUnits implements Units { 
    FAHRENHEIT, CELSIUS 
} 

public interface Units { 
    // some code 
} 
3

Java Dili belirtimine izin verilmez.

14.11. The switch Statement

İfade tipi Char, bayt, kısa, int, Karakter, Byte, Kısa, Tamsayı, dize veya bir enum türü (§8.9) veya bir derleme olması gerektiğini söyler zaman hatası oluşur. İşte

, İfade üzerinde geçiş değeri ( switch(expression)) 'dir. Durumunuzda, ifadenin türü, enum değil, bir arabirim olan Units şeklindedir. O

her durum etikete

Sonraki sabit bir ifade veya bir enum sabiti ad olduğunu sabit bir durum vardır.

Enum constants

enum türüne göre nitelikli değildir, bu yüzden bir anahtar farklı enum türü sabitleri karıştırmak olamaz.

sizin için olası bir çözüm bunu böyle uygulamak olacaktır:

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 
    } 
} 

Bu şekilde Unit can uygulayan her enum - ve mutlaka - "işleme mantığı" içine kapsüllü varsa ve varsa herhangi özel enum sabitleri - özel mantığı kendileri uygulayabilirler. Doğal olarak, bazen her enum sabiti belirli bir uygulamaya sahip olabilir ve enum sınıfı seviyesinde bir jenerik olmayacaktır.

1

Bu kullanım örneğini uygun olabilecek: yerine dev bir anahtar davanın

/** 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

için oldukça yeni Ben işe yarayabilir gibi görünüyor. Bir deneyeceğim. – Caketray

+0

Bunlardan birini unuttun */', btw – Caketray

+0

Teşekkürler. Bu yorum şimdi bitti. – cybersam

İlgili konular