如何在Swift中使用type(of:someVar)作为正确的Type?

时间:2017-10-23 20:20:44

标签: swift generics swift4 swift-protocols associated-types

如何在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”创建的,因此调用将转到实现#1(就好像Request.T只是一些可解码类型,实际上它是可解决的,在引擎盖下)。

实际上,如果我在XCode中设置断点,运行时清楚地知道Request.T在每种情况下都是可解密的类型,即使是在向上转换之后也是如此。

因此,在实现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

请帮助,谢谢。 (我试图使用具有关联类型的协议是愚蠢的吗?为什么我不能使用类型(of:schema),就好像它是一个合适的类型一样..?

1 个答案:

答案 0 :(得分:0)

使用==而不是:

<...>
where R.T == Decodable <...>
where R.T == Decryptable <...>