我有一个符合Equatable的A类和一个继承自A的B类。我为每个类定义了==。
比较两个B对象时,使用正确的==函数来确定相等性。当检查B的数组是否包含对象B时,将调用为A定义的==。
//: Playground - noun: a place where people can play
class A: Equatable {
var id: Int
init(id: Int) {
self.id = id
}
}
class B: A {
}
func ==(lhs: A, rhs: A) -> Bool {
print("Comparing using A's ==")
return false
}
func ==(lhs: B, rhs: B) -> Bool {
print("Comparing using B's ==")
return lhs.id == rhs.id
}
let b1 = B(id: 1)
let b2 = B(id: 2)
let array: [B] = [b1, b2] // an array explicitly defined as containing B objects
print("\((b2 == b2))")
print("\(array.index(of: b2))")
print("\(array.contains(b2))")
输出:
Comparing using B's ==
true
Comparing using A's ==
Comparing using A's ==
nil
Comparing using A's ==
Comparing using A's ==
false
为什么会这样?
编辑:已解决!
正如 Hamish 在下面评论过,这是因为在某些情况下B会依赖A = =,更多信息,请参见第2点:== overload for custom class is not always called
为了解决这个问题,我做了以下工作:我定义了一个名为isEqualTo(object:)
的方法,该方法是从A ==
调用的。该方法被B覆盖。
由于经过另外几次方法调用的开销,这可能会有点效率低一些,但它对我正在处理的数据来说效果还不错。
//: Playground - noun: a place where people can play
class A: Equatable {
var id: Int
init(id: Int) {
self.id = id
}
// define an isEqualTo method which takes another A instance
// this will be called from A's ==
func isEqualTo(object: A) -> Bool {
return self == object
}
}
class B: A {
// override the isEqualTo: method
override func isEqualTo(object: A) -> Bool {
// if we are actually dealing with an object of type B, cast it
// first, then call B's ==
if let bObject = object as? B {
return self == bObject
}
// fallback to A's ==
return super.isEqualTo(object: object)
}
}
func ==(lhs: A, rhs: A) -> Bool {
print("Comparing using A's ==")
// use a designated, overridable method to determine equality
return lhs.isEqualTo(object: rhs)
}
func ==(lhs: B, rhs: B) -> Bool {
print("Comparing using B's ==")
return lhs.id == rhs.id
}
let b1 = B(id: 1)
let b2 = B(id: 2)
let array: [B] = [b1, b2]
print("\((b2 == b2))")
print("\(array.index(of: b2))")
print("\(array.contains(b2))")
输出:
Comparing using B's ==
true
Comparing using A's ==
Comparing using B's ==
Comparing using A's ==
Comparing using B's ==
Optional(1)
Comparing using A's ==
Comparing using B's ==
Comparing using A's ==
Comparing using B's ==
true