【发布时间】:2017-10-23 20:20:44
【问题描述】:
如何在 Swift 中使用 type(of: someVar) 作为正确的类型?
假设我有一些通用协议 Requestable:
protocol Decryptable: Decodable {
var cipher: Cipher
}
protocol Requestable {
associatedtype T
var schema: T
}
protocol Service {
static func invoke<R: Requestable>(_ request: R) -> Void where R.T: Decodable {
// impl. #1
}
static func invoke<R: Requestable>(_ request: R) -> Void where R.T: Decryptable {
// impl. #2
}
}
struct Request<T>: Requestable {
var schema: T
}
服务可以调用其 Schema 可解码或可解密的请求。
但是,由于 Decryptable 符合 Decodable,因此在其他地方我们有一些 Decryptable 值已向上转换为 Decodable,例如:
let myDecodable = myDecryptable as Decodable
// later... in a class that doesn’t know about myDecryptable...
let myRequest = Request(schema: myDecodable)
Service.invoke(myRequest)
现在,当此处调用 Service 调用时,它将路由到第一个实现 (#1)。即,由于请求是使用向上转换的值“myDecodable”创建的,invoke 将转到实现#1(好像 Request.T 只是一些可解码类型,而实际上它是可解密的,在引擎盖下)。
确实,如果我在 XCode 中设置断点,运行时会清楚地知道 Request.T 在任何情况下都是 Decryptable 类型,即使在 is upcast 之后也是如此。
所以在实现 1 中,我尝试了很多方法来将架构可解密的调用路由到实现 2:
typealias ActualType: Decryptable = R.T
if let downcastedRequest = request as? Request<ActualType> {
invoke(downcastedRequest)
}
// FAILS to compile
let schemaType = type(of: request.schema)
if let downcastedRequest = Request<schemaType>(schema: request.schema as? schemaType) {
invoke(downcastedRequest)
}
// FAILS to compile
if let downcastedRequest = Request<type(of: request.schema)>(schema: request.schema as? type(of: request.schema)) {
invoke(downcastedRequest)
}
// FAILS to compile
请帮忙,谢谢。 (我是否愚蠢地尝试使用具有关联类型的协议?为什么我不能在这里使用 type(of: schema) 就好像它是正确的类型一样......?
【问题讨论】:
-
没有回答您的问题,但 Swift 4 中有一个
Decodable协议,用于反序列化。我猜你的Decodable与密码学有关,对吗?
标签: swift generics swift4 swift-protocols associated-types