package kapitel_09 /** * Beispiel aus * * - Algorithmen und Datenstrukturen für Dummies * - von Andreas Gogol-Döring und Thomas Letschert * - Verlag Wiley-VCH; Oktober 2019 * - Kapitel 9, Mengen und ihre Speicherung * * @author A. Gogol-Döring, Th. Letschert */ object AuD_09_03_Equals01_App extends App { /* * Ein Problem des Hashings ist, die Funktion zur Berechnung des Hashcodes vom Typ der zu speichernden * Elemente geliefert werden muss und dass sie zur Gleichheit der Elemente passen muss. * Beides muss vom den Anwender der Hashtabelle kommen. Damit ist die korrekte Arbeit einer ``Systemfunktion'' * vom Verständnis und Geschick der Anwendungsentwickler abhängig. Das gilt generell als das größte Problem des * Hashings. Die Hashfunktion und der Vergleich von Objekten müssen immer zusammen betrachtet werden. In objektorientierten Sprachen * ist die Gleichheit zudem ein erstaunlich komplexes Thema. */ /* * In Java basiert die Gleichheit auf dem Operator \texttt{==} und der Methode \textsl{equals} der universellen Basis-Klasse * Object. Der Operator == prüft stets die Gleichheit der direkt in einer Speicherstelle gespeicherten Werte. * Da Objekte immer nur über Referenzen (Zeiger) zugegriffen werden, prüft == im Endeffekt zwei unterschiedliche Dinge: * * - die Werte-Gleichheit bei Werten mit einem primitiven Typ, * - die Identität von Werten mit einem Klassentyp. * * Als Ausweg für eine benutzerdefinierte Werte-Gleichheit von Werten mit einem Klassentyp kann die Methode equals, * die als Identität entsprechend zu == vordefiniert ist, überschrieben werden. * Das führt dazu, dass in Java \textsl{equals} generell gegenüber \texttt{==} zu bevorzugen ist. * * In Scala sollte == zum Test der Gleichheit verwendet werden. Zum expliziten Test der Identität wird * eq verwendet. Wenn x eq y gilt, dann sind x und y das selbe Objekt. * * Zum Test der Wertegleicheit (das Gleiche das aber nicht unbedingt das selbe ist) == verwendet. * * Die Definition der Wertegleichheit liegt in Scala genau wie in Java in der Hand der Anwendungsentwickler, * die mit einerRedefinition von equals die Gleichheit in ihrem Sinn steuern können. * Ohne eine explizite Redefinition ist equals in Scala so wie in Java ein Test auf Identität. */ class Rabbit (val name: String, val weight: Int) { override def equals(other: Any): Boolean = other match { case that: Rabbit => name == that.name && weight == that.weight case _ => false } override def hashCode(): Int = { val state = Seq(name, weight) state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b) } } class Rabbit_Champion(name: String, weight: Int, val prizes: Int) extends Rabbit (name: String, weight: Int) { override def equals(other: Any): Boolean = other match { case that: Rabbit_Champion => super.equals(that) && prizes == that.prizes case that: Rabbit => super.equals(that) case _ => false } override def hashCode(): Int = { val state = Seq(super.hashCode(), prizes) state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b) } } val x = new Rabbit_Champion("Egon", 5, 7) val y = new Rabbit ("Egon", 5) val z = new Rabbit_Champion("Egon", 5, 10) println(x == y) // true println(y == z) // true println(x == z) // false }