Menu
Coddy logo textTech

Sobrescrita de hashCode & ==

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 71 de 110.

Por padrão, dois objetos em Dart são iguais apenas se forem a exata mesma instância na memória. Isso significa que dois objetos com valores idênticos ainda são considerados 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 - instâncias diferentes!
}

Para comparar objetos por seus valores, você precisa sobrescrever tanto o operador == quanto o hashCode. Estes dois devem sempre ser sobrescritos juntos - se dois objetos são iguais, eles devem ter o mesmo 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 - mesmos valores!
}

O hashCode é crucial para coleções como chaves de Set e Map. O utilitário Object.hash() do Dart combina múltiplos valores em um único código hash. Sem um hashCode adequado, seus objetos não funcionarão corretamente em coleções baseadas em hash, mesmo que o == seja sobrescrito.

challenge icon

Desafio

Fácil

Vamos construir um sistema de coordenadas onde os pontos podem ser comparados por seus valores em vez de seus endereços de memória! Você criará uma classe Coordinate que implementa adequadamente a igualdade baseada em valor, fazendo com que ela funcione corretamente com verificações de igualdade e coleções baseadas em hash, como o Set.

Você organizará seu código em dois arquivos:

  • coordinate.dart: Crie uma classe Coordinate representando um ponto no espaço 2D com os campos final int x e final int y. Sobrescreva tanto o operador == quanto o hashCode para que duas coordenadas com os mesmos valores de x e y sejam consideradas iguais. Use Object.hash() para gerar o código hash a partir de ambos os campos.
  • main.dart: Importe seu arquivo de coordenada e demonstre como a igualdade baseada em valor altera o comportamento de comparação de objetos:
    • Crie dois objetos Coordinate separados, ambos com x: 5 e y: 10
    • Imprima se eles são iguais usando ==
    • Imprima se eles são idênticos (mesma instância) usando identical()
    • Crie um Set<Coordinate> e adicione ambas as coordenadas a ele
    • Imprima o comprimento (length) do conjunto (deve ser 1, já que são iguais!)
    • Crie uma terceira coordenada com x: 3 e y: 7, e adicione-a ao conjunto
    • Imprima o comprimento final do conjunto

Este desafio demonstra por que o hashCode e o == devem sempre ser sobrescritos juntos. O Set usa códigos hash para organizar os elementos, portanto, sem um hashCode adequado, mesmo objetos iguais podem ser armazenados como duplicatas!

Saída esperada:

true
false
1
2

Folha de consulta

Por padrão, dois objetos em Dart são iguais apenas se forem a mesma instância na memória, não se tiverem os mesmos valores:

var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2);  // false - instâncias diferentes!

Para comparar objetos por seus valores, sobrescreva tanto o operador == quanto o hashCode. Estes devem sempre ser sobrescritos 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);
}

Use Object.hash() para combinar múltiplos valores em um único código hash. O hashCode é crucial para coleções como Set e Map - sem ele, objetos iguais não funcionarão corretamente em coleções baseadas em hash.

Para verificar se dois objetos são a mesma instância (não apenas valores iguais), use identical():

print(identical(p1, p2));  // false - instâncias diferentes

Experimente você mesmo

import 'coordinate.dart';

void main() {
  // TODO: Crie dois objetos Coordinate separados, ambos com x: 5 e y: 10

  // TODO: Imprima se eles são iguais usando ==

  // TODO: Imprima se eles são idênticos (mesma instância) usando identical()

  // TODO: Crie um Set<Coordinate> e adicione ambas as coordenadas a ele

  // TODO: Imprima o comprimento (length) do conjunto (deve ser 1, já que eles são iguais!)

  // TODO: Crie uma terceira coordenada com x: 3 e y: 7, adicione-a ao conjunto

  // TODO: Imprima o comprimento final do conjunto
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos