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标准库有这样的协议,最着名的是Collection
或Sequence
。
为了让你创build一个实现Collection
协议的东西或者一系列实现序列协议的东西,标准库采用了一种称为“type-erasure”的技术来创build结构typesAnyCollection<T>
或者AnySequence<T>
。 types删除技术是相当复杂的解释堆栈溢出的答案,但如果你searchnetworking有很多关于它的文章。
我可以推荐一个来自Alex Gallagher的关于YouTube上关联types协议(PAT)的video。