Base In Extension
如果需要为某个 Struct / Classes / Enum 扩展方法,然后并需要为其添加约束(泛型遵循某个协议)
eg: extension Array where Element: TextRepresentable
一、Motivation
我们来举一个例子
假设说我们要为 Array,扩展一个方法,这个方法是当数组中的元素 Element 遵循某个协议 P 的时候才能使用
如果是以前的写法,需要对所有元素进行一个类型的判断 element as? P
protocol P {
func doSomeThing()
}
extension Array: P {
func doSomeThing() {
for element in self {
if let pElement = element as? P {
pElement.doSomeThing()
}else {
print("element is not P")
}
}
}
}
如果在 Swift 4.1, 使用 Conditional Conformance
protocol P {
func doSomeThing()
}
extension Array: P where Element: P {
func doSomeThing() {
for element in self {
element.doSomeThing()
}
}
}
二、Multiple conformances
Swift 中禁止同一类型遵循同一协议两次
protocol P {}
struct X: P {}
extension: P {} // error: X already stated conformance to P
同样的对于 Conditional Conformance, 也同样禁止
protocol HashIdentify {
static func ===(lhs: Self, rhs: Self) -> Bool
}
struct SomeWrapped<Wrapped> {
var wrapped: Wrapped
}
extension SomeWrapped: Equatable where Wrapped: Equatable {
static func ==(lhs: SomeWrapped<Wrapped>, rhs: SomeWrapped<Wrapped>) -> Bool {
return lhs.wrapped == rhs.wrapped
}
}
/* SomeWrapped already stated conformance to Equtable */
extension SomeWrapped: Equtable where Wrapped: HasIdentify {
static func ==(lhs: SomeWrapped<wrapped>, rhs: SomeWrapped<Wrapped>) -> Bool {
return lhs.wrapped === rhs.wrapped
}
}
很显然,SomeWrapped 不能同时拥有两个 fun == 的实现
以下行为也不允许
extension SomeWrapped: Equatable where Wrapped == Int {
static func ==(lhs: SomeWrapped<Wrapped>, rhs: SomeWrapped<Wrapped>) -> Bool {
return lhs.wrapped == rhs.wrapped
}
}
/* SomeWrapped already stated conformance to Equtable */
extension SomeWrapped: Equtable where Wrapped == String {
static func ==(lhs: SomeWrapped<wrapped>, rhs: SomeWrapped<Wrapped>) -> Bool {
return lhs.wrapped === rhs.wrapped
}
}
在上述的 extension 中,有可能 Wrapped: Equtable,也有可能 Wrapped: HasIdentify, 有可能两个同时满足,也有可能两个都不满足
如果是同时满足的情况,可采用 Equatable & HasIdentify
extension SomeWrapped: Equatable where Wrapped: Equatable & HasIdentify {
static func ==(lhs: SomeWrapped<Wrapped>, rhs: SomeWrapped<Wrapped>) -> Bool {
return lhs.wrapped == rhs.wrapped
}
}
三、Implied conditional conformances
protocol P { }
protocol Q : P { }
protocol R : P { }
struct X<T> { }
extension X: Q where T: Q { }
extension X: R where T: R { }
因为 Q: P , R: P,所以 T: Q 和 T: R 均隐式满足 T: P
如果当 T: P 时,他同时满足两个 extension,这时候会出现不确定性,系统将会建议用户新建 T: P 的 extension
extension X: P where T: P {}
除了上述情况, 还有 T: Q, T: R 且 Q: R, R: P 的情况该如何处理
protocol P { }
protocol Q : P { }
protocol R : Q { }
struct X<T> { }
extension X: Q where T: Q { }
extension X: R where T: R { }
也就是说当,T: P 时,同样会存在不确定性,同样系统将会建议用户新建 T: P 的 extension
extension X: P where T: P {}
网友评论