0

I wrote an equals method for class A.

class A(x: Int, s: String) {
  override def equals(that: Any) = that match {
    case a: A => this.x == a.x && this.s == a.s
    case _    => false
  } 
}

Is it correct?

Finkelson
  • 2,921
  • 4
  • 31
  • 49
  • I just posted an answer on another question which is a more detailed answer to your question. It is crucial for instances of your class to correctly implement both `equals` and `hashCode` to properly behave within the Scala collections library. Or suffer unexpected failures. stackoverflow.com/a/56509518/501113 – chaotic3quilibrium Jun 10 '19 at 19:14

2 Answers2

5

Yes that is correct. However you should also override the hashCode method to reflect equality. That is, if you have two instances a and b where a == b, you should ensure that a.hashCode == b.hashCode.

The simplest way to achieve the two is to use a case-class:

case class A(private val x: Int, private val s: String)

This gives you correct equals and hashCode for "free".


If you plan for the possibility that there are sub-classes of A, you may look at Odersky's idea of canEqual (also here).

0__
  • 66,707
  • 21
  • 171
  • 266
0

a better approach is defining on companion object of A an Ordering[A] instance.

object A{
    implicit object aOrdering extends Ordering[A]{
        override def compare(x:A,y:A):Int = ......
    }
}

than on you equals method you should write:

override def equals(that: Any) = that match {
  case a: A => {
        val ordering = implicitly[Ordering[A]] 
        ordering.compare(this,a) == 0 
 }
  case _    => false
} 

this way you can reuse your code i.e scala collections and other places that you need Ordering for this class.

David H
  • 1,346
  • 3
  • 16
  • 29
  • Why not just write it the usual way and utilize the class's `equals` method within the `compare` method? You have to write the equality definition in one place or the other. For classes that don't have a logical ordering you can't use an `Ordering` object, so it would seem more consistent just to write it the normal way everywhere. I don't see any advantage in your way and it seems more complicated and inconsistent. What am I missing? – Luigi Plinge Dec 13 '15 at 17:06
  • if you dont have ordering, its right to only override the equals(). if you do have Ordering, you are having duplicate code, which means you need to maintain both of them – David H Dec 13 '15 at 17:08
  • Why, where's the duplicate code? Your `compare` method should just use the `equals` method defined by the class to determine when to spit out 0. No duplication. – Luigi Plinge Dec 13 '15 at 18:08
  • Whether there is going to be duplicate code depends on how the `compare` method is implemented. It certainly isn't a better approach in general (and where it is, implement `Ordered` instead of creating an implicit `Ordering`). – Alexey Romanov Dec 13 '15 at 19:53
  • you are going to duplicate the code on equals() and on your Ordered/Ordering implementation. Ordered ?!? lets say you want multiple types of ordering i.e ordering for string can be alphabetical / length of string. with Ordered you are stuck with one implementationm, on the other hand you can have multiple Ordering instances for the same class and you can choose your Odering implementaion depends on the conext of your code. much better flexibility. please read about TypeClasses. – David H Dec 14 '15 at 11:49
  • how exactly compare() can use equals() ? equals return Boolean while compare return Int. – David H Dec 14 '15 at 11:56