Menu
Coddy logo textTech

Redéfinition de hashCode & ==

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 71 sur 110.

Par défaut, deux objets en Dart ne sont égaux que s'ils sont la même instance exacte en mémoire. Cela signifie que deux objets ayant des valeurs identiques sont toujours considérés comme différents :

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 - instances différentes !
}

Pour comparer des objets par leurs valeurs, vous devez redéfinir à la fois l'opérateur == et hashCode. Ces deux-là doivent toujours être redéfinis ensemble - si deux objets sont égaux, ils doivent avoir le même code de hachage :

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 - mêmes valeurs !
}

Le hashCode est crucial pour les collections comme les clés de Set et de Map. L'assistant Object.hash() de Dart combine plusieurs valeurs en un seul code de hachage. Sans un hashCode approprié, vos objets ne fonctionneront pas correctement dans les collections basées sur le hachage, même si == est redéfini.

challenge icon

Défi

Facile

Construisons un système de coordonnées où les points peuvent être comparés par leurs valeurs plutôt que par leurs adresses mémoire ! Vous allez créer une classe Coordinate qui implémente correctement l'égalité basée sur les valeurs, ce qui lui permettra de fonctionner correctement avec les vérifications d'égalité et les collections basées sur le hachage comme Set.

Vous organiserez votre code en deux fichiers :

  • coordinate.dart : Créez une classe Coordinate représentant un point dans un espace 2D avec des champs final int x et final int y. Surchargez à la fois l'opérateur == et hashCode afin que deux coordonnées ayant les mêmes valeurs x et y soient considérées comme égales. Utilisez Object.hash() pour générer le code de hachage à partir des deux champs.
  • main.dart : Importez votre fichier de coordonnées et démontrez comment l'égalité basée sur les valeurs modifie le comportement de comparaison des objets :
    • Créez deux objets Coordinate distincts, tous deux avec x : 5 et y : 10
    • Affichez s'ils sont égaux en utilisant ==
    • Affichez s'ils sont identiques (même instance) en utilisant identical()
    • Créez un Set<Coordinate> et ajoutez les deux coordonnées à celui-ci
    • Affichez la longueur de l'ensemble (elle devrait être 1 puisqu'ils sont égaux !)
    • Créez une troisième coordonnée avec x : 3 et y : 7, ajoutez-la à l'ensemble
    • Affichez la longueur finale de l'ensemble

Ce défi démontre pourquoi hashCode et == doivent toujours être surchargés ensemble. Le Set utilise les codes de hachage pour organiser les éléments, donc sans un hashCode approprié, même des objets égaux pourraient être stockés comme des doublons !

Résultat attendu :

true
false
1
2

Aide-mémoire

Par défaut, deux objets en Dart sont égaux uniquement s'ils sont la même instance en mémoire, et non s'ils ont les mêmes valeurs :

var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2);  // false - instances différentes !

Pour comparer des objets par leurs valeurs, surchargez à la fois l'opérateur == et hashCode. Ceux-ci doivent toujours être surchargés ensemble :

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);
}

Utilisez Object.hash() pour combiner plusieurs valeurs en un seul code de hachage. Le hashCode est crucial pour les collections comme Set et Map - sans lui, les objets égaux ne fonctionneront pas correctement dans les collections basées sur le hachage.

Pour vérifier si deux objets sont la même instance (et pas seulement des valeurs égales), utilisez identical() :

print(identical(p1, p2));  // false - instances différentes

Essayez vous-même

import 'coordinate.dart';

void main() {
  // TODO: Créer deux objets Coordinate distincts, tous deux avec x: 5 et y: 10

  // TODO: Afficher s'ils sont égaux en utilisant ==

  // TODO: Afficher s'ils sont identiques (même instance) en utilisant identical()

  // TODO: Créer un Set<Coordinate> et y ajouter les deux coordonnées

  // TODO: Afficher la longueur de l'ensemble (devrait être 1 puisqu'ils sont égaux !)

  // TODO: Créer une troisième coordonnée avec x: 3 et y: 7, l'ajouter à l'ensemble

  // TODO: Afficher la longueur finale de l'ensemble
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet