在 equals 方法中的 Scala 匹配
Scala match in equals method
我是 Scala 的新手,但有不错的 Java 背景。我的问题是关于重写 Scala 中的 equals 方法。以下示例来自 Scala 说明书:
class Person (name: String, age: Int) {
def canEqual(a: Any) = a.isInstanceOf[Person]
override def equals(that: Any): Boolean =
that match {
case that: Person => that.canEqual(this) && this.hashCode == that.hashCode
case _ => false
}
}
我的问题是为什么我们需要
that.canEqual(this)
我的理解是只有当 'that' 是一个人时才会执行该代码。那么,为什么要额外调用 isInstanceOf?
that.canEqual(this)
不是多余的。如果 that
是 Person
的子类的实例,并且定义了它自己的相等性(并且它自己的 canEqual
方法),则这是必要的。
另一方面,this.canEqual(that)
是多余的。
主要目的是确保在Person
的实例和Person
的潜在子类之间的双向相等关系有效可能有自己的 equals 实现。
假设我有:
class Person(...) {
... as defined, but without the `that.canEqual(this)` call
}
class Nobody extends Person {
// contrived, but valid definition
override def equals (that: Any) = false
... and some definition of hashCode that happens to produce same value
}
...
// then
new Person(...) == new Nobody // true
new Nobody == new Person(...) // false
// breaks equals by not being symmetric
更详细的解释 link 由 pedrofurla 在评论中提供:http://www.artima.com/pins1ed/object-equality.html
来自两个不同 类 的两个不同对象可以具有相同的哈希码;因此,您不能仅根据哈希码就说两个对象相等。例如,由于 Dog
定义 hashCode
的方式,具有黄色皮毛和响亮树皮的 Dog
可能具有 20011 年的 hashCode
; RocketShip
设计用于飞往土星的 hashCode
也可能出于非常不相关的原因而具有 20011 年的 hashCode
。显然,这是两个截然不同的对象。但是,如果两个 Dogs
或两个 RocketShips
具有相同的哈希码,那么可以*安全地假设它们是等效对象:必须具有两个等效对象是没有任何意义的(例如,两个 Dogs
有黄色皮毛和响亮的吠声)有两个不同的哈希码,并且拥有两个相同类型的不同对象(例如,一个 Dog
有黑色皮毛)是没有意义的,另一个有棕色毛皮的)具有相同的哈希码。 isInstanceOf
检查可确保您处理的是同一类型的两个对象:哈希码检查可让您快速评估两个对象 是否应该 相同.
(*: 如果有有限个哈希码和无限个属性组合产生唯一Dogs
,那么不可避免地会发生哈希码冲突。即使isInstanceOf
检查也是'不够,但对于大多数情况来说可能已经足够了,因此在食谱中就是一个例子。)
编辑: 参见 here:
Pitfall #2: Changing equals without also changing hashCode.
If two objects are equal according to the equals method, then calling the hashCode method on each of the two objects must produce the same integer result
简而言之,两个相等的对象必须具有相同的哈希码才能履行方法的合同(但没有任何地方说具有相同哈希码的两个对象必须相等!)
编辑 2
由于您有 Java 背景,您可能已经习惯看到以下内容。
public boolean equals(Object other) {
// I am a Dog. If they're not a dog, I can't be equal to them.
if (!(other instanceof Dog))
return false;
// If the other dog's properties are equal to my own, then we're equal.
if (...)
return true;
// If not, we're not equal.
else
return false;
}
您给出的代码示例正在做(大致)相同的事情,用 hashCode
检查代替相等检查。
我是 Scala 的新手,但有不错的 Java 背景。我的问题是关于重写 Scala 中的 equals 方法。以下示例来自 Scala 说明书:
class Person (name: String, age: Int) {
def canEqual(a: Any) = a.isInstanceOf[Person]
override def equals(that: Any): Boolean =
that match {
case that: Person => that.canEqual(this) && this.hashCode == that.hashCode
case _ => false
}
}
我的问题是为什么我们需要
that.canEqual(this)
我的理解是只有当 'that' 是一个人时才会执行该代码。那么,为什么要额外调用 isInstanceOf?
that.canEqual(this)
不是多余的。如果 that
是 Person
的子类的实例,并且定义了它自己的相等性(并且它自己的 canEqual
方法),则这是必要的。
this.canEqual(that)
是多余的。
主要目的是确保在Person
的实例和Person
的潜在子类之间的双向相等关系有效可能有自己的 equals 实现。
假设我有:
class Person(...) {
... as defined, but without the `that.canEqual(this)` call
}
class Nobody extends Person {
// contrived, but valid definition
override def equals (that: Any) = false
... and some definition of hashCode that happens to produce same value
}
...
// then
new Person(...) == new Nobody // true
new Nobody == new Person(...) // false
// breaks equals by not being symmetric
更详细的解释 link 由 pedrofurla 在评论中提供:http://www.artima.com/pins1ed/object-equality.html
来自两个不同 类 的两个不同对象可以具有相同的哈希码;因此,您不能仅根据哈希码就说两个对象相等。例如,由于 Dog
定义 hashCode
的方式,具有黄色皮毛和响亮树皮的 Dog
可能具有 20011 年的 hashCode
; RocketShip
设计用于飞往土星的 hashCode
也可能出于非常不相关的原因而具有 20011 年的 hashCode
。显然,这是两个截然不同的对象。但是,如果两个 Dogs
或两个 RocketShips
具有相同的哈希码,那么可以*安全地假设它们是等效对象:必须具有两个等效对象是没有任何意义的(例如,两个 Dogs
有黄色皮毛和响亮的吠声)有两个不同的哈希码,并且拥有两个相同类型的不同对象(例如,一个 Dog
有黑色皮毛)是没有意义的,另一个有棕色毛皮的)具有相同的哈希码。 isInstanceOf
检查可确保您处理的是同一类型的两个对象:哈希码检查可让您快速评估两个对象 是否应该 相同.
(*: 如果有有限个哈希码和无限个属性组合产生唯一Dogs
,那么不可避免地会发生哈希码冲突。即使isInstanceOf
检查也是'不够,但对于大多数情况来说可能已经足够了,因此在食谱中就是一个例子。)
编辑: 参见 here:
Pitfall #2: Changing equals without also changing hashCode. If two objects are equal according to the equals method, then calling the hashCode method on each of the two objects must produce the same integer result
简而言之,两个相等的对象必须具有相同的哈希码才能履行方法的合同(但没有任何地方说具有相同哈希码的两个对象必须相等!)
编辑 2 由于您有 Java 背景,您可能已经习惯看到以下内容。
public boolean equals(Object other) {
// I am a Dog. If they're not a dog, I can't be equal to them.
if (!(other instanceof Dog))
return false;
// If the other dog's properties are equal to my own, then we're equal.
if (...)
return true;
// If not, we're not equal.
else
return false;
}
您给出的代码示例正在做(大致)相同的事情,用 hashCode
检查代替相等检查。