Protocol只能用作通用约束,因为它具有Self或associatedType的要求

您好我有一个协议的RequestType,它有associatedType模型如下。

public protocol RequestType: class { associatedtype Model var path: String { get set } } public extension RequestType { public func executeRequest(completionHandler: Result<Model, NSError> -> Void) { request.response(rootKeyPath: rootKeyPath) { [weak self] (response: Response<Model, NSError>) -> Void in completionHandler(response.result) guard let weakSelf = self else { return } if weakSelf.logging { debugPrint(response) } } } } 

现在我正在尝试对所有失败的请求进行排队。

 public class RequestEventuallyQueue { static let requestEventuallyQueue = RequestEventuallyQueue() let queue = [RequestType]() } 

但是我得到了let queue = [RequestType]() :Protocol RequestType只能用作通用约束,因为它具有Self或associatedType的要求。

任何帮助,将不胜感激。

假设现在我们调整协议来添加一个使用关联types的例程:

  public protocol RequestType: class { associatedtype Model var path: String { get set } func frobulateModel(aModel: Model) } 

而Swift让你按照你想要的方式创build一个RequestType数组。 我可以将这些请求types的数组传递给一个函数:

 func handleQueueOfRequests(queue: [RequestType]) { // frobulate All The Things! for request in queue { request.frobulateModel(/* What do I put here? */) } } 

我的意思是说,我想把所有的东西都弄成一团,但是我需要知道传递给调用的参数是什么types的。 我的一些RequestType实体可以采用LegoModel ,一些可以采用PlasticModel ,另一些可以采用PeanutButterAndPeepsModel 。 Swift对模糊不满并不满意,所以它不会让你声明一个具有关联types的协议的variables。

同时,当我们知道所有的都使用LegoModel时候,创build一个RequestType的数组是非常有意义的。 这似乎是合理的,这是,但你需要某种方式来expression这一点。

一种方法是创build一个类(或结构,或枚举),使真实types与抽象模型types名称关联:

 class LegoRequestType: RequestType { typealias Model = LegoModel // Implement protocol requirements here } 

现在宣布一个LegoRequestType数组是完全合理的,因为如果我们想要把所有的frobulate ,我们就知道每次都要传入一个LegoModel

与关联types的这种细微差别使任何使用它们的协议变得特殊。 Swift标准库有这样的协议,最着名的是CollectionSequence

为了让你创build一个实现Collection协议的东西或者一系列实现序列协议的东西,标准库采用了一种称为“type-erasure”的技术来创build结构typesAnyCollection<T>或者AnySequence<T> 。 types删除技术是相当复杂的解释堆栈溢出的答案,但如果你searchnetworking有很多关于它的文章。

我可以推荐一个来自Alex Gallagher的关于YouTube上关联types协议(PAT)的video。