2010-10-05 96 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