gpt4 book ai didi

ios - Protocol 只能作为泛型约束,因为它有 Self 或 associatedType 要求

转载 作者:IT王子 更新时间:2023-10-29 04:58:02 25 4
gpt4 key购买 nike

我有一个协议(protocol) 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 要求。

最佳答案

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

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 对这种歧义不满意,因此它不会让您声明具有关联类型的协议(protocol)变量。

与此同时,创建一个 RequestType 的数组也很有意义。当我们知道他们所有人都使用 LegoModel .这看起来很合理,确实如此,但您需要某种方式来表达这一点。

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

class LegoRequestType: RequestType {
typealias Model = LegoModel

// Implement protocol requirements here
}

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

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

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

Swift 5.7 存在主义

Swift 5.7 使用 any 引入显式存在关键词。这将消除“协议(protocol)只能用作通用约束...”错误,但它不能解决此示例 的根本问题。 (不可否认,这个例子是学术性的,用于演示目的,由于其局限性,可能在实际代码中没有用。但它也证明了显式存在不是万灵药。)

这是使用 Swift 5.7 和 any 的代码示例关键字。

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

func frobulateModel(aModel: Model)
}

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

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

现在我们的队列包含存在性集合,并且我们不再有关于“由于自身或关联类型约束而无法在此处使用类型”的错误。但它并没有解决这个例子中的根本问题,因为 frobulateModel方法仍然可以采用任意类型(符合 RequestType 协议(protocol)的实体的关联类型)。

Swift 提供了其他机制来帮助弥补这一点。一般来说,你会想要约束 Model公开所有行为的值(value) Models . frobulateModel方法可能是通用的,并且对参数有约束以遵循该协议(protocol)。或者您可以使用 Swift 5.7 的主要关联类型 ( SE-0346 ) 来帮助约束 Models 的行为在协议(protocol)级别。

所以是的,显式存在主义可以删除 OP 询问的错误消息 - 但它们并不是适用于所有情况的解决方案。

另外,请记住,存在性会导致间接性,这会带来性能问题。在 WWDC session 上,Apple 告诫我们要谨慎使用它们。

关于ios - Protocol 只能作为泛型约束,因为它有 Self 或 associatedType 要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36348061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com