我想使带有协议元素的数组调用数组扩展方法。操场上的代码出现错误:
错误:类型'ObjectProtocol'不符合协议'Equatable'
代码:
extension Array {
func good() {
}
}
protocol ObjectProtocol {
}
extension ObjectProtocol where Self: Equatable {
func isEqualTo(_ other: ObjectProtocol) -> Bool {
guard let otherX = other as? Self else { return false }
return self == otherX
}
}
extension Array where Element: Equatable {
func bad() {}
}
var protocolArray = [ObjectProtocol]()
var array = [1,3,2,5]
array.good() // OK
array.bad() // OK
protocolArray.good() // OK
protocolArray.bad() // error: error: type 'ObjectProtocol' does not conform to protocol 'Equatable'
有什么方法可以实现?
答案 0 :(得分:1)
您的Equatable
一致性是Objective-C版本,而不是Swift版本。
protocol FoobarProtocol: Equatable {}
extension FoobarProtocol {
public static func == (lhs: Self, rhs: Self) -> Bool {
return true // do something useful
}
}
您的问题是关于作为其他Array
元素的协议。这将导致另一个错误:
错误:不支持将“ FoobarProtocol”用作符合协议“ Equatable”的具体类型
这是因为Equatable
一致性只是在另一个协议上的一致性。 static func == (lhs:rhs:)
的默认实现可能会给人以为它是完整的实现,但事实并非如此。 在采用具体类型的协议之前仍然是一个一致性。当在具体实现中使用该协议时,默认实现会自动唤醒。
简而言之: Swift中的协议不能等同。只能是具体类型。
答案 1 :(得分:0)
在Array扩展中实现的功能仅适用于相等类型。您在ObjectProtocol扩展中实现的函数也仅适用于相等类型,但这并不意味着符合ObjectProtocol的对象也将符合等同形式。为此,您可以执行以下操作:
class Custom<T: ObjectProtocol & Equatable>{
var array = [T]()
func doStuff(){
array.bad()
}
}
答案 2 :(得分:0)
如果您发现自己的错误,这很容易解释
错误:类型'ObjectProtocol'不符合协议'Equatable'
在 ObjectProtocol 扩展中,您添加了Self
必须符合Equatable
的约束。
解决方法是
protocol ObjectProtocol {}
extension ObjectProtocol where Self: Equatable {
func isEqualTo(_ other: ObjectProtocol) -> Bool {
guard let otherX = other as? Self else { return false }
return self == otherX
}
}
extension Array where Element: Equatable {
func bad() {
print("I am bad")
}
}
extension Array {
func good() {
print("I am good")
}
}
// I have added a custom Type `Friend` and confirm it to the `ObjectProtocol` and Equatable
struct Friends: ObjectProtocol, Equatable{
var years = 10
}
var protocolArray = [Friends]()
//protocolArray.append(Friends(name: 29))
//protocolArray.append(Friends(name: 50))
var array = [1, 3, 2, 5]
array.good() // OK
array.bad() // OK
protocolArray.good() // OK
protocolArray.bad() // It will work now