You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:21:18