知识卡片

协议不能泛型化改用关联类型

专业/工作 · 756.b

内容

Swift的协议本身不能像类型一样带尖括号占位参数(没有protocol Container<T>这种写法),但可以在协议内部用associatedtype声明一个占位类型,交给每个符合协议的具体类型自己决定填什么(如IteratorProtocol要求associatedtype Elementnext()返回Element?;具体类型可以显式提供typealias Element = T,也可以让编译器从next()的实现签名反推出Element是什么)。这和[[泛型用占位类型换取跨类型复用而不丢失类型安全]]里泛型类型的占位类型方向相反:泛型类型的占位类型由调用方在使用处指定(Stack<Int>),关联类型则由遵从协议的类型自己在实现时锁定,调用方无从干预。这个不对称性是很多人初学Swift协议时的困惑点,也是SequenceCollection等标准库核心协议得以既通用又类型安全的关键机制。

参考来源

《Swift编程权威指南》第22章《泛型》