现在假设我们调整您的协议以添加一个使用关联类型的例程:
public protocol RequestType: class { associatedtype Model var path: String { get set } func frobulateModel(aModel: Model)}Swift可以让您
RequestType按照自己的方式创建数组。我可以将这些请求类型的数组传递给函数:
func handleQueueOfRequests(queue: [RequestType]) { // frobulate All The Things! for request in queue { request.frobulateModel() }}我到了要散布所有东西的地步,但是我需要知道将哪种类型的参数传递给调用。我的某些
RequestType实体可以采用
LegoModel,有些可以采用
PlasticModel,而另一些可以采用
PeanutButterAndPeepsModel。Swift对歧义性不满意,因此它不会让您声明具有关联类型的协议变量。
同时,例如,
RequestType当我们知道它们所有人都使用时,创建一个数组非常有意义
LegoModel。这似乎是合理的,而且确实如此,但是您需要某种表达方式。
一种方法是创建一个将真实类型与抽象Model类型名称相关联的类(或struct或enum):
class LegoRequestType: RequestType { typealias Model = LegoModel // Implement protocol requirements here}现在声明一个数组是完全合理的,
LegoRequestType因为如果我们想要
frobulate所有这些数组,我们知道我们必须
LegoModel每次都传递。
与关联类型的这种细微差别使使用它们的协议变得特别。Swift标准库最著名的协议就是这样的
Collection或
Sequence。
为了使您能够创建一组实现
Collection协议的事物或一组实现序列协议的事物,标准库采用了一种称为“类型擦除”的技术来创建结构类型
AnyCollection<T>或
AnySequence<T>。要在Stack
Overflow答案中进行解释,类型擦除技术相当复杂,但是如果您在网上搜索,则会有很多关于它的文章。
我可以推荐来自Alex Gallagher的有关YouTube
上具有关联类型协议(PAT)的视频。



