无法在Swift的另一个协议中将协议用作关联类型
我有一个协议,Address
该协议继承自另一个协议Validator
,并且Address
满足Validator
扩展要求。
还有另一种协议,FromRepresentable
其要求associatedType
(ValueWrapper
)应该为Validator
。
现在,如果我尝试使用Address
as associatedType
,那么它将无法编译。它说,
推断的类型“地址”(通过匹配要求“ valueForDetail”)无效:不符合“ Validator”。
这种用法非法吗?我们不能像所有的那样用Address
它代替。Validator``Addresses``Validator
下面是我正在尝试的代码。
enum ValidationResult {
case Success
case Failure(String)
}
protocol Validator {
func validate() -> ValidationResult
}
//Address inherits Validator
protocol Address: Validator {
var addressLine1: String {get set}
var city: String {get set}
var country: String {get set}
}
////Fulfill Validator protocol requirements in extension
extension Address {
func validate() -> ValidationResult {
if addressLine1.isEmpty {
return .Failure("Address can not be empty")
}
return .Success
}
}
protocol FormRepresentable {
associatedtype ValueWrapper: Validator
func valueForDetail(valueWrapper: ValueWrapper) -> String
}
// Shipping Address conforming to Address protocol.
// It should also implicitly conform to Validator since
// Address inherits from Validator?
struct ShippingAddress: Address {
var addressLine1 = "CA"
var city = "HYD"
var country = "India"
}
// While compiling, it says:
// Inferred type 'Address' (by matching requirement 'valueForDetail') is invalid: does not conform
// to 'Validator'.
// But Address confroms to Validator.
enum AddressFrom: Int, FormRepresentable {
case Address1
case City
case Country
func valueForDetail(valueWrapper: Address) -> String {
switch self {
case .Address1:
return valueWrapper.addressLine1
case .City:
return valueWrapper.city
case .Country:
return valueWrapper.country
}
}
}
更新: 提交了一个错误。
-
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 use let 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.Address1 let address = ShippingAddress(addressLine1: "", city: "", country: "") addressFrom.valueForDetail(AnyAddress(address))
-
将数据从一个协议发送到另一个协议中?
2021-01-29 关注 0 浏览80 1答案
-
在Swift中将数据源分离到另一个类
2021-01-31 关注 0 浏览61 1答案
-
为什么协议的关联类型在Swift中不使用通用类型语法?
2021-01-31 关注 0 浏览51 1答案
-
在Swift中,如何转换为具有关联类型的协议?
2021-01-31 关注 0 浏览51 1答案
-
类型应为通用函数采用什么协议,以在Swift中将任何数字类型作为参数?
2021-01-31 关注 0 浏览127 1答案
-
TypeError:不可散列的类型:'dict',当dict用作另一个dict的键时
2021-01-29 关注 0 浏览77 1答案
-
在Swift中将列表从一个函数传递到另一个函数
2021-01-31 关注 0 浏览89 1答案
-
TypeError:不可散列的类型:'dict',当dict用作另一个dict的键时[duplicate]
2021-01-31 关注 0 浏览116 1答案
-
一个协议可以被多个类确认。
2020-12-25 关注 0 浏览45 1答案
-
在Swift中将值从一个视图控制器传递到另一个
2021-01-31 关注 0 浏览104 1答案