David已经提到的问题是,一旦将协议限制
associatedtype为特定的(非
@objc)协议,就必须使用具体的类型来满足该要求。
这是因为协议不符合自己-所以这意味着你不能使用
Address,以满足类型的协议的关联型需求符合
Validator,因为
Address是 不是
一个类型符合
Validator。
如我在此处的答案所示,请考虑以下反例:
protocol Validator { init()}protocol Address : Validator {}protocol FormRepresentable { associatedtype ValueWrapper: Validator}extension FormRepresentable { static func foo() { // if ValueWrapper were allowed to be an Address or Validator, // what instance should we be constructing here? // we cannot create an instance of a protocol. print(ValueWrapper.init()) }}// therefore, we cannot say:enum AddressFrom : FormRepresentable { typealias ValueWrapper = Address}
最简单的解决方案是放弃关联类型
Validator上的协议约束
ValueWrapper,从而允许您在方法参数中使用抽象类型。
protocol FormRepresentable { associatedtype ValueWrapper func valueForDetail(valueWrapper: ValueWrapper) -> String}
enum AddressFrom : Int, FormRepresentable { // ... func valueForDetail(valueWrapper: Address) -> String { // ... }}
如果您需要关联的类型约束,并且每个
AddressFrom实例仅期望一个具体的实现
Address作为输入–您可以使用泛型,以便
AddressFrom使用在方法中使用的给定具体地址类型进行初始化。
protocol FormRepresentable { associatedtype ValueWrapper : Validator func valueForDetail(valueWrapper: ValueWrapper) -> String}
enum AddressFrom<T : Address> : Int, FormRepresentable { // ... func valueForDetail(valueWrapper: T) -> String { // ... }}
// replace ShippingAddress with whatever concrete type you want AddressFrom to uselet addressFrom = AddressFrom<ShippingAddress>.Address1
但是,如果您同时需要关联的类型约束, 并且
每个
AddressFrom实例必须能够处理任何类型的输入,则
Address必须使用类型擦除来将任意
Address类型包装为具体类型。
protocol FormRepresentable { associatedtype ValueWrapper : Validator func valueForDetail(valueWrapper: ValueWrapper) -> String}
struct AnyAddress : Address { private var _base: Address var addressLine1: String { get {return _base.addressLine1} set {_base.addressLine1 = newValue} } var country: String { get {return _base.country} set {_base.country = newValue} } var city: String { get {return _base.city} set {_base.city = newValue} } init(_ base: Address) { _base = base }}
enum AddressFrom : Int, FormRepresentable { // ... func valueForDetail(valueWrapper: AnyAddress) -> String { // ... }}
let addressFrom = AddressFrom.Address1let address = ShippingAddress(addressLine1: "", city: "", country: "")addressFrom.valueForDetail(AnyAddress(address))
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)