我有一个Objective-C的情况,其中Java风格的枚举将非常有用。我有一组图层类型,每个图层都有自己的持久性值(以秒为单位存储)。我想将这些图层类型保存在枚举中,因为它们太相似而不能分成单独的类,如下所示:
typedef enum {
ExplosionLayerType,
FireworkLayerType,
FireLayerType,
FireJetLayerType
} FXLayerType;
在Java中,我可以轻松地将这两个值与以下内容相关联:
public enum FXLayerType {
Explosion(3),
Firework(6),
Fire(7),
FireJet(-1);
private int persistence;
FXLayerType(int persistence) {
this.persistence = persistence;
}
}
是否有一种简单的方法可以在Objective-C中创建这样的轻量级类,或者需要采用更原始的方法?
编辑:
各种各样的人建议做这样的事情:
typedef enum {
ExplosionLayerType = 3,
FireworkLayerType = 6
} FXLayerType;
这对我不起作用,因为我可能有这样的东西(Java风格的枚举):
Explosion(3),
Firework(6),
Dust(3);
在Java中,Dust和Explosion将被视为唯一值,但使用C枚举直接赋值将视为完全相同。
答案 0 :(得分:2)
如果您只想要一个类型和值的原始容器,请考虑以下方法:
typedef struct FXLayerValue {
FXLayerType type;
int value;
} FXLayerValue;
然后,如果事情变得复杂或者更好地动态处理,那么类层次结构可能是值得考虑的。警告:如果您有大量要保存和/或创建的对象,则objc类型将过度杀伤并降低性能。
不幸的是,我的Java-Fu不足以了解枚举的所有差异。
答案 1 :(得分:2)
为了模拟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
不是常量指针,只有枚举“literals”被定义为常量。
如上所述,这样做有一个缺点,就是你不能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
能够基于指针的枚举 - 这是一个练习!
这两种设计都具有(dis)优势,可以随时扩展枚举“文字”的数量。
答案 2 :(得分:1)
实际上你可以为C中的枚举键赋值,因为它们只是整数:
typedef enum {
LayerTypeExplosion = 3,
LayerTypeFirework = 6,
LayerTypeFire = 7,
LayerTypeFireJet = -1
} FXLayerType;
您可以将它们用作限制集值,并将其分配给FXLayerType
类型的变量。
FXLayerType myLayerType = LayerTypeFirework;
NSLog(@"Value of myLayerType = %i", myLayerType);
// => "Value of myLayerType = 6"
答案 3 :(得分:0)
这不是100%等效,但这可能是您可以在Objective-C中采用的方法。基本上,创建几个类级别的便捷方法来构建FXLayerType的各种配置。
@interface FXLayerType
{
@private
int persistence;
}
+ (FXLayerType*)fireworkLayerType;
+ (FXLayerType*)explosionLayerType;
+ (FXLayerType*)jetLayerType;
@end
@implementation FXLayerType
+ (FXLayerType*)explosionLayerTypeWithPersistence:(int)persistence
{
FXLayerType* layerType = [[FXLayerType new] autorelease];
layerType->persistence = persistence;
return layerType;
}
+ (FXLayerType*)explosionLayerType
{
return [self explosionLayerTypeWithPersistence:3];
}
+ (FXLayerType*)fireworkLayerType
{
return [self explosionLayerTypeWithPersistence:6];
}
+ (FXLayerType*)jetLayerType
{
return [self explosionLayerTypeWithPersistence:-1];
}
@end
用法:
FXLayerType* aJetLayerType = [FXLayerType jetLayerType];
答案 4 :(得分:0)
我最近将j2objc格式用于枚举。它运作得相当不错。此外,如果您尝试直接从Java对象映射,则可以自动生成枚举。
https://code.google.com/p/j2objc/wiki/Enums
但是,我确实从我的“Enums”中删除了j2objc特定的类。我不想要额外的依赖项。
答案 5 :(得分:0)
基于结构的答案看起来很好,但是当你尝试将Objective-C对象添加到结构中时会失败。鉴于这种限制,真正模仿Java风格的枚举可能比它的价值更多。