一尘不染

协议只能用作一般约束,因为它具有Self或relatedType要求

swift

我有一个协议RequestType,它具有如下的relatedType模型。

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要求,因此只能用作通用约束。


阅读 264

收藏
2020-07-07

共1个答案

一尘不染

现在假设我们调整您的协议以添加一个使用关联类型的例程:

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(/* What do I put here? */)
    }
}

我到了要散布所有东西的地步,但是我需要知道将哪种类型的参数传递给调用。我的某些RequestType实体可以采用LegoModel,有些可以采用PlasticModel,而另一些可以采用PeanutButterAndPeepsModel。Swift对歧义性不满意,因此它不会让您声明具有关联类型的协议变量。

同时,例如,RequestType当我们知道它们所有人都使用时,创建一个数组非常有意义LegoModel。这似乎是合理的,而且确实如此,但是您需要某种表达方式。

一种方法是创建一个将真实类型与抽象Model类型名称相关联的类(或struct或enum):

class LegoRequestType: RequestType {
  typealias Model = LegoModel

  // Implement protocol requirements here
}

现在声明一个数组是完全合理的,LegoRequestType因为如果我们想要frobulate所有这些数组,我们知道我们必须LegoModel每次都传递。

与关联类型的这种细微差别使使用它们的协议变得特别。Swift标准库最著名的协议就是这样的CollectionSequence

为了使您能够创建一组实现Collection协议的事物或一组实现序列协议的事物,标准库采用了一种称为“类型擦除”的技术来创建结构类型AnyCollection<T>AnySequence<T>。要在Stack
Overflow答案中进行解释,类型擦除技术相当复杂,但是如果您在网上搜索,则会有很多关于它的文章。

我可以推荐来自Alex Gallagher的有关YouTube
上具有关联类型协议(PAT)的视频。

2020-07-07