的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!
爲了解決這個問題,確保兩個實體是相同的(子)輸入的equals
定義使用canEqual
:
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
謝謝您的回答!我認爲訣竅是'that.canEqual(this)'而不是'this.canEqual(that)',它會以相反的方式進行檢查以確保equals()的有效性。你知道生成的case類版本是否遵循了你在這裏顯示的相同模式?謝謝! –
@ SiuChingPong-AsukaKenji-我相信它確實,但我不確定。 – Shadowlands