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

Protocol can only be used as a generic constraint because it has Self or associatedType requirements(协议只能用作通用约束,因为它具有 Self 或 associatedType 要求)

本文介绍了协议只能用作通用约束,因为它具有 Self 或 associatedType 要求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个协议 RequestType,它有如下关联类型模型.

I have a protocol RequestType and it has associatedType Model as below.

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) }
        }
    }

}

现在我正在尝试为所有失败的请求创建一个队列.

Now I am trying to make a queue of all failed requests.

public class RequestEventuallyQueue {

    static let requestEventuallyQueue = RequestEventuallyQueue()
    let queue = [RequestType]()

}

但我在 let queue = [RequestType]() 行收到错误,即 Protocol RequestType 只能用作通用约束,因为它具有 Self 或 associatedType 要求.

But I get the error on line let queue = [RequestType]() that Protocol RequestType can only be used as a generic constraint because it has Self or associatedType requirements.

推荐答案

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

Suppose for the moment we adjust your protocol to add a routine that uses the associated type:

public protocol RequestType: class {
    associatedtype Model
    var path: String { get set }

    func frobulateModel(aModel: Model)
}

而 Swift 可以让你以你想要的方式创建一个 RequestType 数组.我可以将这些请求类型的数组传递给函数:

And Swift were to let you create an array of RequestType the way you want to. I could pass an array of those request types into a function:

func handleQueueOfRequests(queue: [RequestType]) {
    // frobulate All The Things!

    for request in queue {
       request.frobulateModel(/* What do I put here? */)
    }
}

我想弄清楚所有事情,但我需要知道要传递给调用的参数类型.我的一些 RequestType 实体可以采用 LegoModel,有些可以采用 PlasticModel,而其他的可以采用 PeanutButterAndPeepsModel.Swift 对歧义不满意,因此它不允许您声明具有关联类型的协议变量.

I get down to the point that I want to frobulate all the things, but I need to know what type of argument to pass into the call. Some of my RequestType entities could take a LegoModel, some could take a PlasticModel, and others could take a PeanutButterAndPeepsModel. Swift is not happy with the ambiguity so it will not let you declare a variable of a protocol that has an associated type.

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

At the same time it makes perfect sense to, for example, create an array of RequestType when we KNOW that all of them use the LegoModel. This seems reasonable, and it is, but you need some way to express that.

一种方法是创建一个将真实类型与抽象模型类型名称相关联的类(或结构或枚举):

One way to do that is to create a class (or struct, or enum) that associates a real type with the abstract Model type name:

class LegoRequestType: RequestType {
  typealias Model = LegoModel

  // Implement protocol requirements here
}

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

Now it's entirely reasonable to declare an array of LegoRequestType because if we wanted to frobulate all of them we know we would have to pass in a LegoModel each time.

关联类型的这种细微差别使得任何使用它们的协议都变得特别.Swift 标准库有类似这样的协议,最著名的是 CollectionSequence.

This nuance with Associated Types makes any protocol that uses them special. The Swift Standard Library has Protocols like this most notably Collection or Sequence.

为了允许您创建实现 Collection 协议的事物数组或实现序列协议的事物集合,标准库采用了一种称为类型擦除"的技术来创建结构类型 AnyCollection<T>AnySequence<T>.类型擦除技术在 Stack Overflow 答案中解释起来相当复杂,但如果你在网上搜索,就会有很多关于它的文章.

To allow you to create an array of things that implement the Collection protocol or a set of things that implement the sequence protocol, the Standard Library employs a technique called "type-erasure" to create the struct types AnyCollection<T> or AnySequence<T>. The type-erasure technique is rather complex to explain in a Stack Overflow answer, but if you search the web there are lots of articles about it.

我可以推荐一个来自 Alex Gallagher 关于关联类型 (PAT) 协议的视频在 YouTube 上.

I can recommend a video from Alex Gallagher on Protocols With Associated Types (PATs) on YouTube.

这篇关于协议只能用作通用约束,因为它具有 Self 或 associatedType 要求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:协议只能用作通用约束,因为它具有 Self 或 associatedType 要求

基础教程推荐