如何在Objective-C中实现类似Java带构造方法的枚举?
嘿,这个问题我太熟悉了!Objective-C里确实没有Java那种自带构造方法的枚举语法,但咱们完全可以用类来模拟出一模一样的功能,甚至还能更灵活。
下面是具体的实现方案,完美对应你给出的Java枚举:
头文件(Food.h)
typedef NS_ENUM(NSInteger, FoodType) { FoodTypeHamburger, FoodTypeFries, FoodTypeHotdog, FoodTypeArtichoke }; @interface Food : NSObject @property (nonatomic, readonly) NSInteger price; @property (nonatomic, readonly) FoodType type; // 获取对应类型的Food实例,和Java枚举的直接引用一致 + (instancetype)hamburger; + (instancetype)fries; + (instancetype)hotdog; + (instancetype)artichoke; // 通用方法:根据类型获取对应的实例 + (instancetype)foodWithType:(FoodType)type; @end
实现文件(Food.m)
@implementation Food // 静态变量存储每个单例实例,保证全局唯一,和Java枚举实例的特性一致 static Food *_hamburger = nil; static Food *_fries = nil; static Food *_hotdog = nil; static Food *_artichoke = nil; // 内部初始化方法,相当于Java枚举的构造方法 - (instancetype)initWithType:(FoodType)type price:(NSInteger)price { if (self = [super init]) { _type = type; _price = price; } return self; } // 每个类方法返回对应的单例实例 + (instancetype)hamburger { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _hamburger = [[Food alloc] initWithType:FoodTypeHamburger price:7]; }); return _hamburger; } + (instancetype)fries { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _fries = [[Food alloc] initWithType:FoodTypeFries price:2]; }); return _fries; } + (instancetype)hotdog { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _hotdog = [[Food alloc] initWithType:FoodTypeHotdog price:3]; }); return _hotdog; } + (instancetype)artichoke { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _artichoke = [[Food alloc] initWithType:FoodTypeArtichoke price:4]; }); return _artichoke; } // 通用方法实现 + (instancetype)foodWithType:(FoodType)type { switch (type) { case FoodTypeHamburger: return [self hamburger]; case FoodTypeFries: return [self fries]; case FoodTypeHotdog: return [self hotdog]; case FoodTypeArtichoke: return [self artichoke]; default: return nil; } } // 禁止外部直接alloc/init,确保只能通过我们提供的类方法获取实例 + (instancetype)allocWithZone:(struct _NSZone *)zone { if (self == [Food class]) { @throw [NSException exceptionWithName:@"InvalidAllocation" reason:@"请使用+hamburger、+fries等类方法获取实例" userInfo:nil]; } return [super allocWithZone:zone]; } @end
使用方式
你可以像Java那样直接引用实例,或者通过类型来获取:
// 直接引用,和Java的Food.HAMBURGER完全对应 Food *burger = [Food hamburger]; NSLog(@"汉堡价格:%ld", (long)burger.price); // 输出7 // 通过类型获取 FoodType selectedType = FoodTypeFries; Food *fries = [Food foodWithType:selectedType]; NSLog(@"薯条价格:%ld", (long)fries.price); // 输出2
为什么这么做?
Objective-C的原生NS_ENUM本质上只是整数的别名,没办法附加额外的属性或行为。用类模拟的方式,既保留了Java枚举的单例实例、不可变属性、类型安全这些核心特性,还能根据需求扩展更多功能(比如添加description方法自定义打印内容,或者实现比较逻辑)。
内容的提问来源于stack exchange,提问作者Elstine P
相关产品推荐
相关产品推荐

