在下面的代码中,我想测试是否x为SpecialController。如果是的话,我想currentValue作为SpecialValue。你怎么做到这一点?如果不使用强制转换,则使用其他技术。
x
SpecialController
currentValue
SpecialValue
那里的最后一行不会编译。错误是: 协议“ SpecialController”仅具有通用要求或关联类型要求,因此只能用作通用约束。
protocol SpecialController { associatedtype SpecialValueType : SpecialValue var currentValue: SpecialValueType? { get } } ... var x: AnyObject = ... if let sc = x as? SpecialController { // does not compile
不幸的是,Swift当前不支持将具有关联类型的协议用作实际类型。但是,从技术上讲这对于编译器是可行的。并且很可能在该语言的未来版本中实现。
在您的情况下,一个简单的解决方案是定义一个“影子协议”,该影子协议SpecialController派生自该影子协议,并允许您currentValue通过协议要求进行访问,而协议要求将其擦除:
// 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!") }