Swift 协议扩展,其中 Self: Equatable 不起作用
Swift protocol extension where Self: Equatable doesn't work
谁能解释为什么这不起作用?我得到一个错误 Binary operator '==' cannot be applied to operands of type 'Self' and 'CustomEquatable'
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return self == other
}
}
请从37:25
观看WWDC 2015 Protocol-Oriented Programming in Swift
这几乎是从视频中直接截取的。你必须有条件地向下转换 other
到 Self
.
如果它是同一类型,您可以使用 ==
否则两个对象都不相等。
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
if let other = other as? Self { return self == other }
return false
}
}
让我们从您的 CustomEquatable
协议开始,没有 扩展名:
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
让我们定义一些用于实验的类型:
struct A: Equatable {
let name: String
}
struct B: Equatable {
let id: Int
}
假设我们希望 A
和 B
符合 CustomEquatable
。那么我们有四种情况需要考虑:
a1.isEqualTo(a2)
是什么意思(其中 a1
和 a2
都是 A
类型)?
b1.isEqualTo(b2)
是什么意思(其中 b1
和 b2
都是 B
类型)?
a.isEqualTo(b)
是什么意思(其中 a
是 A
而 b
是 B
)?
b.isEqualTo(a)
是什么意思(其中 b
是 B
而 a
是 A
)?
对于前两种情况,可能的答案是 a1.isEqualTo(a2)
当且仅当 a1 == a2
和 b1.isEqualTo(b2)
当且仅当 b1 == b2
.
对于后两种情况,我们必须决定是否有办法让 A
等于 B
。最简单的解决方案(我认为)是 A
永远不能等于 B
.
所以我们可以这样写一致性:
extension A: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? A) == self
}
}
extension B: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? B) == self
}
}
这两个一致性的唯一区别是转换类型(在 as?
的右侧)。所以我们可以将一致性分解成这样的协议扩展:
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? Self) == self
}
}
通过这个协议扩展,我们可以使 A
和 B
符合 CustomEquatable
而无需为每个实现 isEqualTo
:
extension A: CustomEquatable { }
extension B: CustomEquatable { }
测试代码:
let a1 = A(name: "a1")
let a2 = A(name: "a2")
let b1 = B(id: 1)
let b2 = B(id: 2)
a1.isEqualTo(a1) // true
a1.isEqualTo(a2) // false
b1.isEqualTo(b1) // true
b1.isEqualTo(b2) // false
a1.isEqualTo(b1) // false
b1.isEqualTo(a1) // false
谁能解释为什么这不起作用?我得到一个错误 Binary operator '==' cannot be applied to operands of type 'Self' and 'CustomEquatable'
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return self == other
}
}
请从37:25
观看WWDC 2015 Protocol-Oriented Programming in Swift这几乎是从视频中直接截取的。你必须有条件地向下转换 other
到 Self
.
如果它是同一类型,您可以使用 ==
否则两个对象都不相等。
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
if let other = other as? Self { return self == other }
return false
}
}
让我们从您的 CustomEquatable
协议开始,没有 扩展名:
protocol CustomEquatable { func isEqualTo(_ other: CustomEquatable) -> Bool }
让我们定义一些用于实验的类型:
struct A: Equatable {
let name: String
}
struct B: Equatable {
let id: Int
}
假设我们希望 A
和 B
符合 CustomEquatable
。那么我们有四种情况需要考虑:
a1.isEqualTo(a2)
是什么意思(其中a1
和a2
都是A
类型)?b1.isEqualTo(b2)
是什么意思(其中b1
和b2
都是B
类型)?a.isEqualTo(b)
是什么意思(其中a
是A
而b
是B
)?b.isEqualTo(a)
是什么意思(其中b
是B
而a
是A
)?
对于前两种情况,可能的答案是 a1.isEqualTo(a2)
当且仅当 a1 == a2
和 b1.isEqualTo(b2)
当且仅当 b1 == b2
.
对于后两种情况,我们必须决定是否有办法让 A
等于 B
。最简单的解决方案(我认为)是 A
永远不能等于 B
.
所以我们可以这样写一致性:
extension A: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? A) == self
}
}
extension B: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? B) == self
}
}
这两个一致性的唯一区别是转换类型(在 as?
的右侧)。所以我们可以将一致性分解成这样的协议扩展:
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? Self) == self
}
}
通过这个协议扩展,我们可以使 A
和 B
符合 CustomEquatable
而无需为每个实现 isEqualTo
:
extension A: CustomEquatable { }
extension B: CustomEquatable { }
测试代码:
let a1 = A(name: "a1")
let a2 = A(name: "a2")
let b1 = B(id: 1)
let b2 = B(id: 2)
a1.isEqualTo(a1) // true
a1.isEqualTo(a2) // false
b1.isEqualTo(b1) // true
b1.isEqualTo(b2) // false
a1.isEqualTo(b1) // false
b1.isEqualTo(a1) // false