在Swift中,如何转换为具有关联类型的协议?

Rob*_*b N 20 generics protocols associated-types swift swift3

在下面的代码中,我想测试是否xSpecialController.如果是的话,我想得到currentValue一个SpecialValue.你怎么做到这一点?如果没有演员,那么其他一些技巧.

最后一行不会编译.错误是:协议"SpecialController"只能用作通用约束,因为它具有Self或关联类型要求.

protocol SpecialController {
    associatedtype SpecialValueType : SpecialValue
    var currentValue: SpecialValueType? { get }
}
...
var x: AnyObject = ...
if let sc = x as? SpecialController {  // does not compile
Run Code Online (Sandbox Code Playgroud)

Ham*_*ish 14

不幸的是,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!")
}
Run Code Online (Sandbox Code Playgroud)