Эмулировать целое число перечисления C ++ с помощью перечисления Java - PullRequest
0 голосов
/ 06 октября 2010

Я пытаюсь перевести некоторый код C ++ на Java. Я ищу лучший способ эмулировать этот тип парадигмы C ++ в Java - я думаю, что enums, вероятно, ответ, но я открыт для всего

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

По сути, я ищу способ "расширить" значения перечисления Java.

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

не прекращает резать.

Мне нравится идея создания нового объекта для строгой типизации.

Опять же, я ищу лучший образец для использования здесь. Я мог бы легко обойтись с несколькими публичными статическими финалами int UNKNOWN и т. Д.

Ответы [ 2 ]

3 голосов
/ 06 октября 2010

Одним из преимуществ перечислений Java является то, что они по сути являются объектами, как и все остальные. В частности, вы можете иметь методы для констант и заставить свой enum реализовывать интерфейсы:

interface Useful {
    void doStuff();
}

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

Таким образом, вместо того, чтобы принимать аргументы типа enum, ваши методы могут принять любую реализацию интерфейса и, в частности, предоставить материал по умолчанию, если константы enum реализуют все необходимое.

Они также могут иметь членов:

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, но часто, заставляя перечисление реализовывать необходимый код, вы получите более поддерживаемый код)

2 голосов
/ 06 октября 2010

Если бы каждое значение Type было просто целым числом, то я бы, вероятно, выбрал несколько статических целочисленных значений в классе.

Просто для записи, что-то вроде этого работает более или менее безопасно для типов.Я не могу определить, оправдана ли сложность, не зная больше о проблеме.

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) { ... } 
     }
);

Может быть, это немного эзотерично.Но он в некотором смысле допускает «легкую рассылку» на сайте вызывающего абонента и расширяемое перечисление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...