[英]canEqual() in the scala.Equals trait
从源代码scala/Equals.scala
( 这里 ):
package scala
trait Equals extends scala.Any {
def canEqual(that: scala.Any): scala.Boolean
def equals(that: scala.Any): scala.Boolean
}
在文档中,它说:
应该从每个设计良好的equals方法调用的方法,该方法在子类中被重写。
我随机选择了一个扩展scala.Equals
的类,这个类很容易理解。 我选择了scala.Tuple2[+T1, +T2]
,它扩展了特征scala.Product[T1, T2]
,后者又扩展了特征scala.Product
,后者又扩展了特征scala.Equals
。
不幸的是,似乎因为scala.Tuple2
是一个case类 ,所以canEqual()
和equals()
方法是自动生成的,因此无法在源代码scala/Tuple2.scala
( 这里 )中找到。
我的问题是:
scala.Equals
的好时机? canEqual()
应该如何实现? equals()
使用canEqual()
的最佳实践(或样板文件)是什么? 提前致谢!
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!
要解决此问题,请在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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.