Чтобы эмулировать перечисления Java, нам нужно нечто сопоставимое (может быть операндами ==
и т. Д.), Которое может иметь поля и быть легковесным. Это предполагает структуры и, необязательно, указатели на структуры. Вот пример последнего:
FXLayerType.h:
typedef const struct { int persistence; } FXLayerType;
extern FXLayerType * const LayerTypeExplosion;
extern FXLayerType * const LayerTypeFirework;
extern FXLayerType * const LayerTypeDust;
FXLayerType.m:
#import "FXLayerType.h"
const FXLayerType _LayerTypeExplosion = { 3 };
const FXLayerType _LayerTypeFirework = { 6 };
const FXLayerType _LayerTypeDust = { 3 };
FXLayerType * const LayerTypeExplosion = &_LayerTypeExplosion;
FXLayerType * const LayerTypeFirework = &_LayerTypeFirework;
FXLayerType * const LayerTypeDust = &_LayerTypeDust;
Таким образом, FXLayerType
сам по себе является постоянной структурой, тогда как, как и в случае объектов Obj-C, мы всегда используем указатели на эти структуры. Реализация создает 3 постоянных структуры и 3 постоянных указателя на них.
Теперь мы можем написать код, такой как:
FXLayerType *a, *b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(@"%d, %d\n", a == b, a->persistence == b->persistence);
Которые будут выводить «0, 1» - a
и b
- это разные перечисления (0), но с одинаковым постоянством (1). Обратите внимание, что a
и b
не являются константными указателями, только константы enum определены как константы.
Как написано, это имеет тот недостаток, что вы не можете switch
для значения перечисления. Однако, если это необходимо, просто добавьте второе поле, скажем tag
, и инициализируйте его уникальным значением, используя реальное перечисление, скажем FXLayerStyleTag
. Вы также можете удалить косвенность, если вы всегда рады сравнить теги (например, a.tag ==
b.tag`). Это дает вам:
FXLayerType.h:
typedef enum { ExplosionTag, FireworkTag, DustTag } FXLayerTypeTag;
typedef struct { FXLayerTypeTag tag; int persistence; } FXLayerType;
extern const FXLayerType LayerTypeExplosion;
extern const FXLayerType LayerTypeFirework;
extern const FXLayerType LayerTypeDust;
FXLayerType.m:
#import "FXLayerType.h"
const FXLayerType LayerTypeExplosion = { ExplosionTag, 3 };
const FXLayerType LayerTypeFirework = { FireworkTag, 6 };
const FXLayerType LayerTypeDust = { DustTag, 3 };
Использование:
FXLayerType a, b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(@"%d, %d\n", a.tag == b.tag, a.persistence == b.persistence);
Разница между этими двумя конструкциями заключается в том, что первые обводят указатели, а вторые структуры могут быть больше. Вы можете комбинировать их, чтобы получить switch
способных перечислений на основе указателей - это оставлено как упражнение!
Обе эти конструкции также имеют (не) преимущество, заключающееся в том, что число перечисляемых "литералов" может быть увеличено в любое время.