Menu
Coddy logo textTech

Sobrescritura de hashCode y ==

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 71 de 110.

Por defecto, dos objetos en Dart solo son iguales si son exactamente la misma instancia en memoria. Esto significa que dos objetos con valores idénticos se siguen considerando diferentes:

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 - ¡instancias diferentes!
}

Para comparar objetos por sus valores, necesitas sobrescribir tanto el operador == como hashCode. Estos dos siempre deben sobrescribirse juntos: si dos objetos son iguales, deben tener el mismo código hash:

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 - ¡mismos valores!
}

El hashCode es crucial para colecciones como las claves de Set y Map. El ayudante Object.hash() de Dart combina múltiples valores en un único código hash. Sin un hashCode adecuado, tus objetos no funcionarán correctamente en colecciones basadas en hash incluso si se sobrescribe ==.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de coordenadas donde los puntos se puedan comparar por sus valores en lugar de sus direcciones de memoria! Crearás una clase Coordinate que implemente correctamente la igualdad basada en valores, haciendo que funcione correctamente con las comprobaciones de igualdad y las colecciones basadas en hash como Set.

Organizarás tu código en dos archivos:

  • coordinate.dart: Crea una clase Coordinate que represente un punto en el espacio 2D con los campos final int x y final int y. Sobrescribe tanto el operador == como el hashCode para que dos coordenadas con los mismos valores de x e y se consideren iguales. Utiliza Object.hash() para generar el código hash a partir de ambos campos.
  • main.dart: Importa tu archivo de coordenadas y demuestra cómo la igualdad basada en valores cambia el comportamiento de comparación de objetos:
    • Crea dos objetos Coordinate separados, ambos con x: 5 e y: 10
    • Imprime si son iguales usando ==
    • Imprime si son idénticos (la misma instancia) usando identical()
    • Crea un Set<Coordinate> y añade ambas coordenadas a él
    • Imprime la longitud del conjunto (¡debería ser 1 ya que son iguales!)
    • Crea una tercera coordenada con x: 3 e y: 7, añádela al conjunto
    • Imprime la longitud final del conjunto

Este desafío demuestra por qué hashCode y == siempre deben sobrescribirse juntos. El Set utiliza códigos hash para organizar los elementos, por lo que sin un hashCode adecuado, ¡incluso los objetos iguales podrían almacenarse como duplicados!

Salida esperada:

true
false
1
2

Hoja de referencia

Por defecto, dos objetos en Dart son iguales solo si son la misma instancia en memoria, no si tienen los mismos valores:

var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2);  // false - ¡instancias diferentes!

Para comparar objetos por sus valores, sobrescribe tanto el operador == como hashCode. Estos siempre deben sobrescribirse juntos:

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

Usa Object.hash() para combinar múltiples valores en un solo código hash. El hashCode es crucial para colecciones como Set y Map; sin él, los objetos iguales no funcionarán correctamente en colecciones basadas en hash.

Para comprobar si dos objetos son la misma instancia (no solo valores iguales), usa identical():

print(identical(p1, p2));  // false - instancias diferentes

Pruébalo tú mismo

import 'coordinate.dart';

void main() {
  // TODO: Crea dos objetos Coordinate separados, ambos con x: 5 e y: 10

  // TODO: Imprime si son iguales usando ==

  // TODO: Imprime si son idénticos (la misma instancia) usando identical()

  // TODO: Crea un Set<Coordinate> y añade ambas coordenadas a él

  // TODO: Imprime la longitud del conjunto (¡debería ser 1 ya que son iguales!)

  // TODO: Crea una tercera coordenada con x: 3 e y: 7, y añádela al conjunto

  // TODO: Imprime la longitud final del conjunto
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos