Swift:覆盖子类中的==仅在超类中调用==
我有一个类A,它符合Equatable协议并实现== function。在子类B中,我使用更多检查覆盖==。
但是,当我在B的两个实例数组(两者都具有类型Array< A>)之间进行比较时,调用A = A。当然,如果我将两个数组的类型更改为Array< B>,则调用B来调用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的相等性的原因包含B的是自由函数的重载是静态解决的,而不是动态解析的 – 也就是说,在编译时基于类型,而不是在运行时基于指向的值。
这并不奇怪,因为==未在类中声明,然后在子类中重写。这似乎是非常有限的,但老实说,使用传统的OO技术定义多态相等是极其(并且看似困难)的。有关详细信息,请参阅this link和this paper。 天真的解决方案可能是在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 } } 你还需要做一个吗?跳舞,因为你需要确定右手参数是否是B(如果等于直接取B,那么它就不是合法的覆盖)。 这里还隐藏着一些可能令人惊讶的行为: let x: [A] = [B()] let y: [A] = [A()] // this runs B’s equalTo x == y // this runs A’s equalTo y == x 也就是说,参数的顺序会改变行为。这不好 – 人们希望平等是对称的。所以你真的需要上面链接中描述的一些技术才能正确解决这个问题。 在这一点上,您可能会觉得这一切都变得有点不必要了。它可能是,特别是在Swift标准库的Equatable文档中给出以下注释:
鉴于此,你可能真的想重新考虑使用你的Equatable实现,如果你实现相等的方式不是你对两个相等的值相互替换感到满意的方式。避免这种情况的一种方法是将对象标识视为相等的度量,并根据===实现==,这对于超类只需要执行一次。或者,你可以问自己,你真的需要实现继承吗?如果没有,请考虑抛弃它并使用值类型,然后使用协议和泛型来捕获您正在寻找的多态行为。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |