Swift:重写子类中的==结果仅在超类中调用==
我有一个类Swift:重写子类中的==结果仅在超类中调用==,swift,overriding,equality,Swift,Overriding,Equality,我有一个类a,它符合equalable协议并实现=函数。在子类BI中,使用更多检查覆盖= 但是,当我在B的两个实例数组(它们都具有类型Array)之间进行比较时,会调用A的=。当然,如果我将两个数组的类型都更改为Array,则调用B的= 我提出了以下解决方案: A.swift: internal func ==(lhs: A, rhs: A) -> Bool { if lhs is B && rhs is B { return lhs as! B
a
,它符合equalable
协议并实现=
函数。在子类B
I中,使用更多检查覆盖=
但是,当我在B
的两个实例数组(它们都具有类型Array
)之间进行比较时,会调用A
的=
。当然,如果我将两个数组的类型都更改为Array
,则调用B
的=
我提出了以下解决方案:
A.swift:
internal func ==(lhs: A, rhs: A) -> Bool {
if lhs is B && rhs is B {
return lhs as! B == rhs as! B
}
return ...
}
它看起来非常难看,必须对
A
的每个子类进行扩展。有没有办法确保首先调用子类的=
?对于数组和更多信息调用a
的等式的原因
天真的解决方案可能是在a
中定义一个动态调度函数,然后定义=
来调用它:
class A: Equatable {
func equalTo(rhs: A) -> Bool {
// whatever equality means for two As
}
}
func ==(lhs: A, rhs: A) -> Bool {
return lhs.equalTo(rhs)
}
然后,当您实现B
时,您将覆盖equalTo
:
class B: A {
override func equalTo(rhs: A) -> Bool {
return (rhs as? B).map { b in
return // whatever it means for two Bs to be equal
} ?? false // false, assuming a B and an A can’t be Equal
}
}
你仍然必须像跳舞一样做一个,因为你需要确定右边的参数是否是aB
(如果equalTo
直接接受aB
,它就不是合法的覆盖)
这里还隐藏着一些可能令人惊讶的行为:
let x: [A] = [B()]
let y: [A] = [A()]
// this runs B’s equalTo
x == y
// this runs A’s equalTo
y == x
也就是说,参数的顺序会改变行为。这并不好——人们期望平等是对称的。所以你真的需要上面链接中描述的一些技术来正确地解决这个问题
在这一点上,你可能会觉得这一切都变得有点不必要了。特别是在Swift标准库中的equalable
文档中给出了以下注释:
相等意味着可替代性。当x==y
,x
和y
在任何只取决于其值的代码中都是可互换的
类实例标识由三个相等值区分==
是
值得注意的是,它不是实例值的一部分。暴露其他非价值
不鼓励equalable
类型的方面,以及
应在文件中明确指出暴露的问题
有鉴于此,如果实现相等的方式不是两个相等的值被彼此替换,那么您可能会认真地重新考虑对equalable
实现的喜爱。避免这种情况的一种方法是将对象标识看作是平等的度量,并在===/COD>中实现<代码>=< /代码>,这只需要为超级类做一次。或者,您可以问自己,您真的需要实现继承吗?如果不是,请考虑放弃它并使用值类型,然后使用协议和泛型来捕获您正在寻找的多态行为。我遇到了类似的问题,因为我想在MKPoPANTANTITY子类上使用<代码>差异(从:)/代码>(继承自NSObjor)。即使我将
func==
添加到我的注释子类中,difference(from:
仍然会调用NSObject的=
实现。我相信这只是比较了两个对象的内存位置,这不是我想要的(from:
正常工作,我必须实现覆盖函数isEqual(\uObject:Any?)->Bool{
用于我的注释子类。在正文中,我会确保对象
与我的子类的类型相同,然后在那里进行比较。非常感谢详细的回答和您的辛勤工作!稍后我将查看链接。另一个问题:如果扩展中声明了equalable
协议一致性
,您不能覆盖它。