48

I don't quite understand why when we compare two instance with the same properties of a class without overriding the equals method that it will give a false. But it will give a true when we compare two instances of a case class. For example

 class A(val name: String, val id: Int)
 case class B(name: String, id: Int)

 object Test {
    val a1 = new A('a',1)
    val a2 = new A('a',1)
    println(a1 == a2)   //this returns false

    var b1 = B('b',1)
    var b2 = B('b',1)
    println(b1 == b2)   //this returns true

 }

Could someone explain why, please?

wheaties
  • 35,646
  • 15
  • 94
  • 131
peter
  • 8,333
  • 17
  • 71
  • 94
  • I just posted an answer on another question which addresses what to do with a class (not a case class). https://stackoverflow.com/a/56509518/501113 – chaotic3quilibrium Jun 08 '19 at 19:45

1 Answers1

66

A case class implements the equals method for you while a class does not. Hence, when you compare two objects implemented as a class, instead of case class, what you're comparing is the memory address of the objects.

It's really the same issues as when you have to deal with equality in Java. See this Artima blog post about writing equals in Java (and Scala) written by Bill Venners, Martin Odersky, and Lex Spoon.

Jonik
  • 80,077
  • 70
  • 264
  • 372
wheaties
  • 35,646
  • 15
  • 94
  • 131
  • 2
    On those few occassions when I need to write my own `equals` (thank you, Scala!) I always refresh my memory of the issues and techniques by consulting chapter 28, "Object Equality" of "Programming in Scala" (that's the chapter number and title in the 1st ed., it might be different in the 2nd.) – Randall Schulz Feb 28 '14 at 18:50
  • wondering why scala chooses to implement the equals method for case class but not class ? – peter Mar 14 '14 at 02:17
  • 5
    @user1389813 For `case class` what should be compared is straight forward to reason, the constructor parameters. For other classes which may be parameter-less, how should they do it? There's no "easy" way to reason it out. – wheaties Mar 14 '14 at 12:57
  • 1
    Holly shit I wasn't aware of this for half a year now. I must have left tons of bugs out there... You wanna tell me that everytime you mix in a trait to a case class you'll create a class, not a case class? This is so stupid ! – lisak Jan 05 '15 at 22:32
  • @lisak No! A `case class` is _always_ a `case class`. Mixing in a trait just adds whatever that trait will add. – wheaties Jan 06 '15 at 01:56
  • @wheaties shit I've overlooked that A is a class. I thought that the way of instantiation mattered `new A() / A()`, thanks, I was wondering how that could be possible.. – lisak Jan 06 '15 at 10:54
  • Here's an idiomatic solution for non-case classes: https://stackoverflow.com/a/56509518/501113 – chaotic3quilibrium Aug 16 '21 at 19:53