在 Swift 中,如何转换为具有关联类型的协议? [英] In Swift, how to cast to protocol with associated type?
问题描述
在下面的代码中,我想测试 x
是否是 SpecialController
.如果是,我想将 currentValue
作为 SpecialValue
.你怎么做到这一点?如果不是用演员表,那就是其他一些技巧.
In the following code, I want to test if x
is a SpecialController
. If it is, I want to get the currentValue
as a SpecialValue
. How do you do this? If not with a cast, then some other technique.
那里的最后一行不会编译.有错误是:Protocol "SpecialController" 只能用作泛型约束,因为它有 Self 或相关的类型要求.
The last line there won't compile. There error is: Protocol "SpecialController" can only be used as a generic constraint because it has Self or associated type requirements.
protocol SpecialController {
associatedtype SpecialValueType : SpecialValue
var currentValue: SpecialValueType? { get }
}
...
var x: AnyObject = ...
if let sc = x as? SpecialController { // does not compile
推荐答案
不幸的是,Swift 目前不支持使用关联类型作为实际类型的协议.然而,对于编译器来说,技术上是可行的;它很可能会在该语言的未来版本中实现.
Unfortunately, Swift doesn't currently support the use of protocols with associated types as actual types. This however is technically possible for the compiler to do; and it may well be implemented in a future version of the language.
在您的情况下,一个简单的解决方案是定义一个 SpecialController
派生自的影子协议",并允许您通过类型擦除它的协议要求访问 currentValue
:
A simple solution in your case is to define a 'shadow protocol' that SpecialController
derives from, and allows you to access currentValue
through a protocol requirement that type erases it:
// This assumes SpecialValue doesn't have associated types – if it does, you can
// repeat the same logic by adding TypeErasedSpecialValue, and then using that.
protocol SpecialValue {
// ...
}
protocol TypeErasedSpecialController {
var typeErasedCurrentValue: SpecialValue? { get }
}
protocol SpecialController : TypeErasedSpecialController {
associatedtype SpecialValueType : SpecialValue
var currentValue: SpecialValueType? { get }
}
extension SpecialController {
var typeErasedCurrentValue: SpecialValue? { return currentValue }
}
extension String : SpecialValue {}
struct S : SpecialController {
var currentValue: String?
}
var x: Any = S(currentValue: "Hello World!")
if let sc = x as? TypeErasedSpecialController {
print(sc.typeErasedCurrentValue as Any) // Optional("Hello World!")
}
这篇关于在 Swift 中,如何转换为具有关联类型的协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!