alexgbelov alexgbelov - 2 months ago 22
Scala Question

Scala match in equals method

I'm new to Scala, but have a decent Java background. My question is about overriding the equals method in Scala. The following example is from the Scala cookbook:

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?

Answer

that.canEqual(this) is not redundant. 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).

this.canEqual(that) on the other hand would be redundant.

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.

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

Comments