简体   繁体   English

斯卡拉匹配方法等于

[英]Scala match in equals method

I'm new to Scala, but have a decent Java background. 我是Scala的新手,但是拥有不错的Java背景。 My question is about overriding the equals method in Scala. 我的问题是关于重写Scala中的equals方法。 The following example is from the Scala cookbook: 以下示例来自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
     }
}

My question is why we need 我的问题是为什么我们需要

that.canEqual(this)

My understanding is that that code will only be executed if 'that' is a person. 我的理解是,只有在“那个”是一个人的情况下,该代码才会被执行。 So, why the extra call to isInstanceOf? 那么,为什么要额外调用isInstanceOf?

that.canEqual(this) is not redundant. that.canEqual(this)不是多余的。 It is necessary in case that is an instance of a subclass of Person that has defined it's own equality (and it's own canEqual method). 如果这是Person子类的一个实例,该实例定义了它自己的相等性(并且它是自己的canEqual方法) that则很有必要。

this.canEqual(that) on the other hand would be redundant. this.canEqual(that)将是多余的。

The main purpose is to ensure that the equality relation is valid in both directions between an instance of Person and potentially a subclass of Person that may have it's own implementation of equals. 主要目的是确保相等关系 Person实例与可能具有自己的equals实现的Person子类之间的两个方向上均有效。

Suppose I have: 假设我有:

 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

More detailed explanation link provided by pedrofurla in the comments: http://www.artima.com/pins1ed/object-equality.html pedrofurla在评论中提供了更详细的解释链接: http : //www.artima.com/pins1ed/object-equality.html

Two different objects from two separate classes can have the same hash code; 来自两个不同类的两个不同对象可以具有相同的哈希码。 you therefore cannot say that two objects are equal based on their hash code alone. 因此,您不能仅凭其哈希码就说两个对象相等。 For example, a Dog with yellow fur and a loud bark might have hashCode of 20011 because of the way a Dog defines hashCode ; 例如, Dog ,黄色的皮毛和一个响亮的吠声可能hashCode的20011的,因为路上Dog定义hashCode ; a RocketShip designed to fly to Saturn might also have a hashCode of 20011 for a very unrelated reason. 出于非常不相关的原因,设计要飞往土星的RocketShip也可能具有20011的hashCode Clearly, these are two very different objects. 显然,这是两个截然不同的对象。 If, however, two Dogs or two RocketShips have the same hash code then it is probably* safe to assume they're equivalent objects: it wouldn't make any sense to have to have two equivalent objects (eg, two Dogs with yellow fur and loud barks) have two different hash codes, and it wouldn't make sense to have two different objects of the same type (eg, one Dog with black fur, another with brown fur) have the same hash code. 但是,如果两个Dogs或两个RocketShips具有相同的哈希码,则可以很安全地假定它们是等效的对象:必须具有两个等效的对象(例如,两个带有黄色毛皮的Dogs毫无意义)和大声的吠声)具有两个不同的哈希码,并且使两个不同类型的对象(例如,一个黑色毛皮的Dog ,另一个棕色毛皮的Dog )具有相同的哈希码是没有意义的。 The isInstanceOf check lets you ensure that you're dealing with two objects of the same type: the hash code check allows you to quickly assess whether or not two objects should be equivalent. isInstanceOf检查使您可以确保处理两个相同类型的对象:哈希码检查使您可以快速评估两个对象是否等效。

(*: If there are a finite number of hash codes and an infinite combination of attributes producing unique Dogs , then there will inevitably be hash code collisions. Even the isInstanceOf check isn't sufficient, but is probably good enough for most cases and hence in the cookbook as an example.) (*:如果存在数量有限的哈希码和属性的无限组合产生唯一的Dogs ,那么不可避免地会发生哈希码冲突。即使isInstanceOf检查也是不够的,但对于大多数情况来说可能就足够了,因此以食谱为例。)

Edit: See here : 编辑:这里

Pitfall #2: Changing equals without also changing hashCode. 陷阱2:在不更改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 如果根据equals方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果

In short, two equal objects must have the same hash code to fulfill the method's contract (but nowhere does it say that two objects with equal hash codes must be equal!) 简而言之,两个相等的对象必须具有相同的哈希码才能满足方法的约定(但没有任何地方说具有相等的哈希码的两个对象必须相等!)

Edit 2 As you have a Java background, you're likely used to seeing something of the following. 编辑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;
 }

The code sample you've given is doing (roughly) the same thing, with the hashCode check substituting for an equality check. 您提供的代码示例在做(大致)相同的事情,用hashCode检查代替了相等检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM