无法在Swift的另一个协议中将协议用作关联类型

无法在Swift的另一个协议中将协议用作关联类型,第1张

无法在Swift的另一个协议中将协议用作关联类型

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))


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4901037.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-12
下一篇 2022-11-12

发表评论

登录后才能评论

评论列表(0条)

保存