2010-10-05 97 views
0

我正試圖將一些C++代碼翻譯成Java。我正在尋找最好的方式來模擬這種類型的C++模式的在Java中 - 我想枚舉可能是答案,但我接受任何用Java Enum模擬C++枚舉整數

C++代碼:

typedef UInt32 Type; 
enum { UNKNOWN, QUIT, SYSTEM, TIMER, LAST } 
... 
Type newType = UNKNOWN; 
Type nextType = LAST + 1; 
... 
// "Register" the new type 
newType = nextType; 
nextType++; 
... 
switch (newType) { 
    case UNKNOWN: 
    case QUIT: 
    ... 
    case LAST: 
      // Ignore unset or predefined types 
    default: 
      // Some type other than the predefined. Do something special 

基本上我」 m尋找一種方法來「擴展」Java枚舉的值。

enum Type { UNKNOWN, QUIT, SYSTEM, TIMER, LAST } 

不退出削減它。

我喜歡爲強打字製作新對象的想法。

再次,我正在尋找最佳模式在這裏使用。我可以很容易地通過一些公共靜態final int UNKNOWN來浮動,等等。

+0

您是否承諾使用switch語句?還是會有其他派遣機制呢? – 2010-10-05 22:32:30

+0

@Burleigh Bear:代碼中的開關只是確定它是否是未知的。所以是的,可能任何派遣將工作 – Shaun 2010-10-06 00:12:15

回答

2

如果Type的每個值只是一個整數,那麼我可能會去一堆靜態final int in一類。

只是爲了記錄,類似這樣的工作或多或少類型安全地工作。我不能確定複雜性是否有必要,而不瞭解更多的問題。

public class abstract Type 
{ 
    public static final Type UNKNOWN = registerStd("UNKNOWN"); 
    ... 
    public static final Type TIMER  = registerStd("TIMER"); 

    // use this to keep track of all the types 
    private static final List<Type> REGISTERED = ... 

    //This will do your switch statement for you, implemented by 
    // anonymous subclasses 
    public abstract void dispatch(Type onMe); 

    // here's how you make the standard ones 
    private static Type registerStd(String name) 
    { 
     Type heresOne = new Type(name) 
     { 
      // note, it's a no-op 
      public void dispatch(DoStuffer algorithm) {} 
     }; 
     REGISTERED.add(heresOne); 
     return heresOne; 
    } 

    //here's how you make the non-standard ones 
    public static Type registerNew(String name) 
    { 
     Type heresOne = new Type(name) 
     { 
      public void dispatch(DoStuffer algorithm) {algorithm.execute(this)} 
     }; 
     REGISTERED.add(heresOne); 
     return heresOne; 
    } 

} 

public interface DoStuffer 
{ 
    public void execute(Type onMe); 
} 

//Then your code becomes 
Type newType = Type.registerNew("NewType"); 

newType.dispatch 
(
    new DoStuffer() 
    { 
     public void algorithm(Type forMe) { ... } 
    } 
); 

也許這是一個有點深奧。但它在某種意義上允許在調用者站點進行「輕鬆調度」和可擴展的枚舉。

3

Java枚舉的一個優點是,它們基本上就像所有其他對象一樣。特別是,你可以對常數的方法,讓你的枚舉實現接口:而不是採取枚舉類型的參數,你的方法可以接受該接口的任何實現,特別是

interface Useful { 
    void doStuff(); 
} 

enum Foo implements Useful { 
    DEFAULT { 
     public void doStuff() { 
      ... 
     } 
    }, 
    MAGIC { 
     public void doStuff() { 
      ... 
     } 
    } 
} 

所以,通過讓枚舉常量實現所需的任何東西來提供默認的東西。

它們還可具有成員:

enum Explicit { 
    FIRST(0), SECOND(1), THIRD(2); 

    private final int value; 

    private Explicit(int v) { 
     this.value = v; 
    } 
} 

。注意,常數具有內部數值(反映恆定的其對等體之間的位置),它是可訪問的使用ordinal方法:

assert Explicit.FIRST.ordinal() == 0; 

但依靠這是有點危險。使用序號值時,

enum Explicit { 
    FIRST(0), NEWELT(-1), SECOND(1), THIRD(2); 

    private final int value; 

    private Explicit(int v) { 
     this.value = v; 
    } 
} 

:如果你要在數據庫中(比如說)堅持枚舉常量,那麼下面的變化會打破代碼。出於這個原因,序列化機制在序列化枚舉值時使用常量的名稱而不是它的位置。

所以:

Type.X + 1 

Enum.values()[Enum.X.ordinal() + 1] 

和開關可以使用由枚舉本身(您可以使用Java中switch語句中枚舉實現的接口進行建模,但往往,使得枚舉實現必要的代碼將產生更多可維護的代碼)

+0

是的,這幾乎是我所擁有的。不幸的是,enum.values()[LAST.ordinal()+ 1]將超出範圍。我需要像「擴展」值那樣的枚舉。 – Shaun 2010-10-05 22:40:38

+2

@Shaun。請參閱編輯。使用接口而不是枚舉值,並允許(客戶端代碼?無論如何)通過提供該接口的新實現來提供擴展。枚舉仍然適用於實現有限範圍的默認行爲。 – Dirk 2010-10-05 22:42:32