使用带关联类型的Swift协议存疑:为何尖括号语法可正常运行?
问题解答
你看到的是Swift 5.7引入的**主关联类型(Primary Associated Types)**语法,它解决了带关联类型协议使用时的冗长问题,同时你代码里的any其实还是存在的,只是语法上更简洁了,下面详细解释:
1. 主关联类型的作用
protocol ItemListVM<ItemType>这种尖括号标注,是把ItemType声明为协议的主关联类型。在Swift 5.7之前,要指定带关联类型协议的具体关联类型,必须用where子句:
// 旧写法 let viewModel: any ItemListVM where ItemType == CashItemModel
而主关联类型允许我们直接用尖括号<CashItemModel>来指定关联类型,本质是上面旧写法的语法糖,代码更简洁易读。
2. 为什么代码能运行
- 你的
CashListVM遵守ItemListVM时,因为dict的类型是[String: [CashItemModel]],Swift会自动推断ItemType为CashItemModel,所以它符合any ItemListVM<CashItemModel>的类型要求。 - 这里的
any是必须的:带关联类型的协议本身是“存在类型(Existential Type)”,必须用any来明确进行类型擦除(这是Swift 5.6开始的强制语法要求)。你之前以为尖括号语法无效,其实是混淆了主关联类型和非存在类型的用法——主关联类型只是简化了存在类型的声明,并没有消除类型擦除。
3. 关于性能影响
你担心的any带来的性能开销确实存在:类型擦除会带来少量的运行时开销(比如动态分发),但在绝大多数业务场景下,这种开销可以忽略不计。只有在极端高频调用的代码路径(比如每秒执行百万次的循环),才需要考虑用具体类型代替存在类型来优化性能。
总结
你的代码完全合法,核心是Swift 5.7的主关联类型语法简化了带关联类型协议的存在类型声明,any依然存在(只是语法上和尖括号结合更简洁),性能影响在常规开发中无需过度担忧。
内容的提问来源于stack exchange,提问作者M.Serag
相关产品推荐
相关产品推荐

