alexgbelov alexgbelov - 1 month ago 4
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


My understanding is that that code will only be executed if 'that' is a person. So, why the extra call to isInstanceOf?


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: