15.2. Metody equals, hashCode, toString

Klasy przypadku mogą definiować własne wersje metod equals, hashCode i toString, ale jeśli tego nie zrobią, to zostaną automatycznie wyposażone w domyślne implementacje tych metod. Domyślne metody equals, hashCode i toString w swoim działaniu biorą pod uwagę wartości elementów instancji klasy, natomiast argumenty innych, niż pierwsza lista parametrów oraz wartości składowych klasy w niej zdefiniowanych nie są przez nie brane pod uwagę. Plik CaseClassA.scala definiuje klasę przypadku A, która oprócz elementów ma zdefiniowane parametry na drugiej liście parametrów oraz definiuje składową f.

Plik CaseClassA.scala:
case class A(a:Int, b:String, c:Long)(d:Int, val e:String) {
  var f = a + d
}

Poniższe dwie instancje klasy A są traktowane jako równe, mimo posiadania innych wartości parametrów d i e oraz składowej f. Mają również równe wartości hashCode oraz takie same reprezentacje tekstowe.

scala> val a1 = new A(1,"a",2L)(4,"a1")
a1: A = A(1,a,2)

scala> val a2 = new A(1,"a",2L)(6,"a2")
a2: A = A(1,a,2)

scala> a1.f == a2.f
res0: Boolean = false

scala> a1 == a2
res1: Boolean = true

scala> a1.hashCode == a2.hashCode
res2: Boolean = true

scala> a1.toString == a2.toString
res3: Boolean = true

Jeśli klasa przypadku definiuje własne wersje metod equals, hashCode lub toString, to te wersje mają pierwszeństwo przed domyślnie generowanymi wersjami. Klasa przypadku B, zdefiniowana w pliku CaseClassB.scala, definiuje wspomniane metody, odwołując się w nich do metod zdefiniowanych w klasie nadrzędnej, czyli w tym przypadku AnyRef.

Plik CaseClassB.scala:
case class B(a:Int, b:String, c:Long) {
  override def equals(that: Any) = super.equals(that)
  override def hashCode = super.hashCode
  override def toString = super.toString
}

W rezultacie, dwie instancje klasy są traktowane jako różne, mimo posiadania takich samych wartości elementów. Podobnie wartości hashCode oraz reprezentacje tekstowe obu instancji są różne.

scala> val b1 = new B(1,"b",2L)
b1: B = B@9c38eb

scala> val b2 = new B(1,"b",2L)
b2: B = B@dda234

scala> b1 != b2
res4: Boolean = true
scala> b1.hashCode != b2.hashCode
res5: Boolean = true

scala> b1.toString != b2.toString
res6: Boolean = true

Jeśli klasa przypadku dziedziczy metody equals, hashCode lub toString zdefiniowane w klasie innej niż AnyRef, to te wersje również mają pierwszeństwo przed domyślnie generowanymi wersjami.

Plik CaseClassesCD.scala:
class C {
  override def equals(that: Any) = super.equals(that)
  override def hashCode = super.hashCode
  override def toString = super.toString
}
case class D(a:Int, b:String, c:Long) extends C

Klasa przypadku D, z pliku CaseClassesCD.scala, nie definiuje własnych wersji tych metod, ale dziedziczy je z klasy C. Te odziedziczone wersje mają pierwszeństwo przed wersjami domyślnymi.

scala> val d1 = new D(1,"d",2L)
d1: D = D@18f9349

scala> val d2 = new D(1,"d",2L)
d2: D = D@1956878

scala> d1 != d2
res7: Boolean = true

scala> d1.hashCode != d2.hashCode
res8: Boolean = true

scala> d1.toString != d2.toString
res9: Boolean = true

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.