5月27日 11:50

Swift 枚举的关联值和原始值有什么区别?怎么用?

Swift 的枚举比其他语言强得多——每个 case 可以携带关联值(不同类型的数据),也可以有原始值(同类型的预填充值)。关联值是"每个实例存不同的数据",原始值是"每个 case 对应一个固定值"。

关联值让枚举变成"带数据的标签":case success(User) 携带一个 User,case failure(Error) 携带一个 Error。原始值让枚举变成"有名字的常量":case mercury = 1, venus, earth,rawValue 自动递增。

用 switch 匹配关联值时,可以提取数据:case .success(let user)。如果所有关联值都用 let/let,简写为 case let .success(user)

追问

关联值和原始值能同时用吗?

不能。一个枚举要么有关联值要么有原始值,不能两者兼有。原始值要求所有 case 共享同一类型(Int/String/Character/Float/Double),关联值每个 case 可以不同。需要两者时,用关联值 + 计算属性模拟 rawValue。

原始值的自动赋值规则是什么?

Int 类型从 0 开始递增,可以指定起始值:case mercury = 1, venus, earth 则分别是 1、2、3。String 类型默认是 case 名字本身。手动指定了某个 case 的 rawValue,后面的自动递增。注意 rawValue 必须唯一,重复会编译报错。

枚举可以嵌套吗?

可以。枚举可以嵌套在 struct/class/enum 内部,用于表达层级关系。比如 AST.Expression.Literal.number(42)。嵌套枚举的 case 仍然可以用 .caseName 简写(类型推断时)。

枚举和 struct 相比什么时候用枚举?

状态是互斥的用枚举(只能是 A、B、C 中的一种),状态是组合的用 struct(可以同时有 A 和 B)。网络请求结果用枚举(成功或失败,不会同时),用户配置用 struct(可以同时有多个设置)。枚举强制穷举检查,适合有限状态机。

indirect enum 是什么?

枚举的 case 引用自身时(递归枚举),需要加 indirect 关键字。比如链表:indirect enum List { case empty; case node(Int, List) }。不加 indirect 编译器报错——因为递归类型的内存大小不确定,indirect 告诉编译器用引用语义存储。

写段代码

swift
// 关联值 enum Result<Success, Failure: Error> { case success(Success) case failure(Failure) } // 原始值 enum Planet: Int { case mercury = 1, venus, earth, mars } Planet.earth.rawValue // 3 Planet(rawValue: 3) // Optional(Planet.earth) // 提取关联值 enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } let code = Barcode.upc(8, 85909, 51226, 3) switch code { case let .upc(a, b, c, d): print("\(a)-\(b)-\(c)-\(d)") case let .qrCode(str): print(str) } // 递归枚举 indirect enum Tree { case leaf(Int) case node(Tree, Tree) }
标签:Swift