Menu
Coddy logo textTech

hashCode & == überschreiben

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 71 von 110.

Standardmäßig sind zwei Objekte in Dart nur dann gleich, wenn sie genau dieselbe Instanz im Speicher sind. Das bedeutet, dass zwei Objekte mit identischen Werten immer noch als unterschiedlich betrachtet werden:

class Point {
  int x, y;
  Point(this.x, this.y);
}

void main() {
  var p1 = Point(3, 4);
  var p2 = Point(3, 4);
  print(p1 == p2);  // false - unterschiedliche Instanzen!
}

Um Objekte anhand ihrer Werte zu vergleichen, müssen Sie sowohl den ==-Operator als auch hashCode überschreiben. Diese beiden müssen immer zusammen überschrieben werden – wenn zwei Objekte gleich sind, müssen sie denselben Hash-Code haben:

class Point {
  final int x, y;
  Point(this.x, this.y);
  
  @override
  bool operator ==(Object other) {
    if (other is! Point) return false;
    return x == other.x && y == other.y;
  }
  
  @override
  int get hashCode => Object.hash(x, y);
}

void main() {
  var p1 = Point(3, 4);
  var p2 = Point(3, 4);
  print(p1 == p2);  // true - gleiche Werte!
}

Der hashCode ist entscheidend für Sammlungen wie Set- und Map-Schlüssel. Darts Hilfsfunktion Object.hash() kombiniert mehrere Werte zu einem einzigen Hash-Code. Ohne einen ordnungsgemäßen hashCode funktionieren Ihre Objekte in Hash-basierten Sammlungen nicht korrekt, selbst wenn == überschrieben wurde.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Koordinatensystem bauen, in dem Punkte nach ihren Werten und nicht nach ihren Speicheradressen verglichen werden können! Sie werden eine Coordinate-Klasse erstellen, die wertbasierte Gleichheit ordnungsgemäß implementiert, sodass sie korrekt mit Gleichheitsprüfungen und hash-basierten Sammlungen wie Set funktioniert.

Sie werden Ihren Code in zwei Dateien organisieren:

  • coordinate.dart: Erstellen Sie eine Coordinate-Klasse, die einen Punkt im 2D-Raum mit den Feldern final int x und final int y darstellt. Überschreiben Sie sowohl den ==-Operator als auch hashCode, sodass zwei Koordinaten mit denselben x- und y-Werten als gleich betrachtet werden. Verwenden Sie Object.hash(), um den Hash-Code aus beiden Feldern zu generieren.
  • main.dart: Importieren Sie Ihre Koordinatendatei und demonstrieren Sie, wie wertbasierte Gleichheit das Verhalten beim Objektvergleich verändert:
    • Erstellen Sie zwei separate Coordinate-Objekte, beide mit x: 5 und y: 10
    • Geben Sie aus, ob sie mit == gleich sind
    • Geben Sie aus, ob sie identisch sind (dieselbe Instanz), indem Sie identical() verwenden
    • Erstellen Sie ein Set<Coordinate> und fügen Sie beide Koordinaten hinzu
    • Geben Sie die Länge des Sets aus (sie sollte 1 sein, da sie gleich sind!)
    • Erstellen Sie eine dritte Koordinate mit x: 3 und y: 7, und fügen Sie diese dem Set hinzu
    • Geben Sie die endgültige Länge des Sets aus

Diese Herausforderung zeigt, warum hashCode und == immer zusammen überschrieben werden müssen. Das Set verwendet Hash-Codes, um Elemente zu organisieren. Ohne einen korrekten hashCode könnten selbst gleiche Objekte als Duplikate gespeichert werden!

Erwartete Ausgabe:

true
false
1
2

Spickzettel

Standardmäßig sind zwei Objekte in Dart nur dann gleich, wenn sie dieselbe Instanz im Speicher sind, nicht wenn sie dieselben Werte haben:

var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2);  // false - unterschiedliche Instanzen!

Um Objekte anhand ihrer Werte zu vergleichen, überschreiben Sie sowohl den ==-Operator als auch hashCode. Diese müssen immer zusammen überschrieben werden:

class Point {
  final int x, y;
  Point(this.x, this.y);
  
  @override
  bool operator ==(Object other) {
    if (other is! Point) return false;
    return x == other.x && y == other.y;
  }
  
  @override
  int get hashCode => Object.hash(x, y);
}

Verwenden Sie Object.hash(), um mehrere Werte zu einem einzigen Hash-Code zu kombinieren. Der hashCode ist entscheidend für Collections wie Set und Map – ohne ihn funktionieren gleiche Objekte in Hash-basierten Collections nicht korrekt.

Um zu prüfen, ob zwei Objekte dieselbe Instanz sind (nicht nur gleiche Werte), verwenden Sie identical():

print(identical(p1, p2));  // false - unterschiedliche Instanzen

Probier es selbst

import 'coordinate.dart';

void main() {
  // TODO: Erstelle zwei separate Coordinate-Objekte, beide mit x: 5 und y: 10

  // TODO: Gib aus, ob sie gleich sind, unter Verwendung von ==

  // TODO: Gib aus, ob sie identisch sind (dieselbe Instanz), unter Verwendung von identical()

  // TODO: Erstelle ein Set<Coordinate> und füge beide Koordinaten hinzu

  // TODO: Gib die Länge des Sets aus (sollte 1 sein, da sie gleich sind!)

  // TODO: Erstelle eine dritte Koordinate mit x: 3 und y: 7 und füge sie dem Set hinzu

  // TODO: Gib die finale Länge des Sets aus
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung