To emulate Java enum's we need something which is comparable (can be operands of ==
etc.), which can have fields, and is lightweight. This suggests structs, and optionally pointers to structs. Here is an example of the latter:
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;
So FXLayerType
itself is a constant struct, while as with Obj-C objects we always use pointers to these structs. The implementation creates 3 constant structs and 3 constant pointers to them.
We can now write code such as:
FXLayerType *a, *b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(@"%d, %d\n", a == b, a->persistence == b->persistence);
Which will output "0, 1" - a
and b
are different enums (0) but have the same persistence (1). Note here a
and b
are not constant pointers, only the enum "literals" are defined as constants.
As written this has the disadvantage that you cannot switch
on an enum value. However if that is needed just add a second field, say tag
, and init it with a unique value using a real enum, say FXLayerStyleTag
. You can also remove the indirection if you are happy to always compare tags (e.g. a.tag ==
b.tag`). This gives you:
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 };
Use:
FXLayerType a, b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(@"%d, %d\n", a.tag == b.tag, a.persistence == b.persistence);
A difference between the two designs is the first passes around pointers while the second structures, which may be larger. You can combine them, to get switch
able pointer-based enums - that is left as an exercise!
Both these designs also have the (dis)advantage that the number of enum "literals" can be extended at any time.