hashCode- & ==-Überschreibung
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 exakt 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.
Aufgabe
EinfachLassen 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 korrekt implementiert, sodass sie mit Gleichheitsprüfungen und Hash-basierten Sammlungen wie Set korrekt funktioniert.
Sie werden Ihren Code in zwei Dateien organisieren:
coordinate.dart: Erstellen Sie eineCoordinate-Klasse, die einen Punkt im 2D-Raum mit den Feldernfinal int xundfinal int ydarstellt. Überschreiben Sie sowohl den==-Operator als auchhashCode, sodass zwei Koordinaten mit denselben x- und y-Werten als gleich betrachtet werden. Verwenden SieObject.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:5und 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:
3und y:7, und fügen Sie diese dem Set hinzu - Geben Sie die endgültige Länge des Sets aus
- Erstellen Sie zwei separate
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
2Probier 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, füge sie dem Set hinzu
// TODO: Gib die endgültige Länge des Sets aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler