Swift中如何创建强制实现者为String RawValue枚举的协议/混入策略
解决Swift中带关联类型协议无法作为具体类型使用的问题
问题根源
你遇到的错误是因为Role协议继承了RawRepresentable,而RawRepresentable带有关联类型RawValue——带有关联类型的协议无法直接作为具体类型(比如数组元素类型)使用,只能作为泛型约束。你的第二种协议定义是正确的,但依然绕不开关联类型的限制:
protocol Role: RawRepresentable where RawValue == String { }
解决方案:类型擦除(Type Erasure)
通过创建一个具体的AnyRole结构体,包装所有符合Role协议的枚举实例,把关联类型的信息封装起来,就能将其作为具体类型使用。
1. 定义类型擦除结构体
struct AnyRole: Role, Equatable, Codable { let rawValue: String // 初始化方法,接受任意符合Role的实例 init<R: Role>(_ role: R) { self.rawValue = role.rawValue } // 实现RawRepresentable的必要初始化方法 init?(rawValue: String) { self.rawValue = rawValue } }
2. 修改枚举与使用方式
enum BusinessRole: Role, Codable { case bronzeAccess = "BRONZE_ACCESS" case premiumAccess = "PREMIUM_ACCESS" case platinumAccess = "PLATINUM_ACCESS" } enum PaymentRole: Role, Codable { case creditCard case wallet } // 调整allRoles()返回AnyRole数组 func allRoles() -> [AnyRole] { return [ AnyRole(BusinessRole.bronzeAccess), AnyRole(PaymentRole.creditCard), AnyRole(PaymentRole.wallet) ] } // 现在可以正常声明数组并进行判断 var roles: [AnyRole] = allRoles() let canPayWithCreditCard = roles.contains(AnyRole(PaymentRole.creditCard))
其他可选思路
- 如果不需要跨枚举类型的数组,仅在单一枚举场景下使用,可以用泛型函数处理,但这不符合你当前的需求。
- 如果可以放弃枚举的类型安全,直接用
[String]存储角色标识,但这会丢失枚举带来的编译期检查优势,不推荐。
内容的提问来源于stack exchange,提问作者Guilherme Guimarães
相关产品推荐
相关产品推荐

