The 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