来自源码scala/Equals.scala
( here ):
package scala
trait Equals extends scala.Any {
def canEqual(that: scala.Any): scala.Boolean
def equals(that: scala.Any): scala.Boolean
}
在文档中,它说:
A method that should be called from every well-designed equals method that is open to be overridden in a subclass.
我随机选择了一个扩展
scala.Equals
的类这很容易理解。我选了scala.Tuple2[+T1, +T2]
,它扩展了特征 scala.Product[T1, T2]
,这反过来又扩展了特征 scala.Product
,这反过来又扩展了特征 scala.Equals
.不幸的是,似乎是因为
scala.Tuple2
是一个案例类,canEqual()
和 equals()
方法是自动生成的,因此在源代码中找不到 scala/Tuple2.scala
( here )。我的问题是:
scala.Equals
? canEqual()
被执行? canEqual()
在 equals()
? 提前致谢!
PS:如果有关系,我使用的是 Scala 2.11.7。
最佳答案
canEquals
方法用于覆盖期望equals
应该是对称的——也就是说,当(且仅当)a.equals(b)
为真,则 b.equals(a)
也应该是真的。当将类的实例与子类的实例进行比较时,可能会出现与此有关的问题。例如。
class Animal(numLegs: Int, isCarnivore: Boolean) {
def equals(other: Any) = other match {
case that: Animal =>
this.numLegs == that.numLegs &&
this.isCarnivore == that.isCarnivore
case _ => false
}
}
class Dog(numLegs: Int, isCarnivore: Boolean, breed: String) extends Animal(numLegs, isCarnivore) {
def equals(other: Any) = other match {
case that: Dog =>
this.numLegs == that.numLegs &&
this.isCarnivore == that.isCarnivore &&
this.breed == that.breed
case _ => false
}
}
val cecil = new Animal(4, true)
val bruce = new Dog(4, true, "Boxer")
cecil.equals(bruce) // true
bruce.equals(cecil) // false - cecil isn't a Dog!
要解决此问题,请使用
canEqual
确保两个实体属于相同(子)类型。在equals
的定义中:class Animal(numLegs: Int, isCarnivore: Boolean) {
def canEqual(other: Any) = other.isInstanceOf[Animal]
def equals(other: Any) = other match {
case that: Animal =>
that.canEqual(this) &&
this.numLegs == that.numLegs &&
this.isCarnivore == that.isCarnivore
case _ => false
}
}
class Dog(numLegs: Int, isCarnivore: Boolean, breed: String) extends Animal(numLegs, isCarnivore) {
def canEqual(other: Any) = other.isInstanceOf[Dog]
def equals(other: Any) = other match {
case that: Dog =>
that.canEqual(this) &&
this.numLegs == that.numLegs &&
this.isCarnivore == that.isCarnivore &&
this.breed == that.breed
case _ => false
}
}
val cecil = new Animal(4, true)
val bruce = new Dog(4, true, "Boxer")
cecil.equals(bruce) // false - call to bruce.canEqual(cecil) returns false
bruce.equals(cecil) // false
关于scala - scala.Equals trait 中的 canEqual(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32093526/