我正在创建用于通用协议的类确认,该通用协议具有接受associatedtype
类型参数的方法,我使用Xcode为我生成存根:
import UIKit
struct SomeObject: Codable {
var id: String?
var name: String?
}
protocol INetworkManager {
associatedtype ResponseObject
func get(url: String, ofType: ResponseObject.Type, completion: (ResponseObject?, Error?) -> Void)
}
class NetworkManager: INetworkManager {
typealias ResponseObject = Codable
func get(url: String, ofType: ResponseObject.Protocol, completion: (ResponseObject?, Error?) -> Void) {
completion(SomeObject(id: "1", name: "hello"), nil)
}
}
我不是ResponseObject.Type
而是为我生成ResponseObject.Protocol
,实际上我不知道这个ResponseObject.Protocol
是什么,并且我不能像这样传递参数SomeObject.self
:
let networkManager = NetworkManager()
networkManager.get(url: "http://whatever.com", ofType: SomeObject.self) { (responseObject, error) in
print("got response object named: \(responseObject.name)")
}
编译器给我这个错误:
error: Cannot convert value of type 'SomeObject.Type' to expected argument type 'NetworkManager.ResponseObject.Protocol' (aka '(Decodable & Encodable).Protocol')
我认为我的实现存在问题,任何人都可以给我提出任何想法?
谢谢!
答案 0 :(得分:0)
这不是关联类型的工作方式。 get
应该在响应类型上是通用的,但是网络管理器本身在某些特定响应类型上不是通用的。我相信您的意思是这样的:
protocol NetworkManager {
func get<ResponseObject>(url: String,
ofType: ResponseObject.Type,
completion: (Result<ResponseObject, Error>) -> Void)
where ResponseObject: Decodable
}
class TrivialNetworkManager: NetworkManager {
func get<ResponseObject>(url: String,
ofType: ResponseObject.Type,
completion: (Result<ResponseObject, Error>) -> Void)
where ResponseObject: Decodable {
completion(.success(SomeObject(id: "1", name: "hello"))
}
}
有关此特定问题的更详尽的版本,您可以阅读我的protocol series,但此处的重要概念是NetworkManager的ResponseType不变,因此没有理由将其ResponseType关联类型。
您写的是想说:“某些网络管理器将具有可编码的ResponseType,而其他网络管理器将具有其他类型的ResponseType。”不是“某些其他特定的响应类型(如用户)”,而是“其响应类型必须符合的其他协议”。尽管可以想到构建类似的东西,但它要复杂得多,并且您需要解释精确的用例才能进行设计。具体来说,您需要显示协议的几种具体实现,以查看要提取的共享代码类型。