Dart Object Identity & Equality

Summary: in this tutorial, you’ll learn about object identity & equality and how to implement object equality properly.

Object identity

In Dart, all classes implicitly inherit from the Object class directly or indirectly. Therefore, all classes can access the == operator from the Object class.

The == operator returns true if two objects are equal. By default, the == operator compares two objects by their identities. For example:

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

void main() {
  var p1 = Point(x: 10, y: 20);
  var p2 = Point(x: 10, y: 20);
  var result = p1 == p2;
  print(result);
}Code language: JavaScript (javascript)

Output:

falseCode language: JavaScript (javascript)

How it works.

  • First, define a Point class with two properties x and y.
  • Second, create two instances of the Point class p1 and p2 with the same x and y values.
  • Third, use the == operator to compare p1 with p2. Even though p1 and p2 have the same x and y coordinates, they are not equal. The reason is that p1 and p2 are different objects.

In fact, p1 and p2 are variables that reference separate objects that have the same x and y values. To check if two variables reference the same object, you use the identical() function.

For example, the following returns false because p1 and p2 reference different Point objects:

var p1 = Point(x: 10, y: 20);
var p2 = Point(x: 10, y: 20);
var result = identical(p1, p2);
print(result);Code language: PHP (php)

However, the following returns true because p1 and p2 reference the same object:

var p1 = Point(x: 10, y: 20);
var p2 = p1;
var result = identical(p1, p2);
print(result);Code language: PHP (php)

Object equality

If you want two Point objects with the same x and y to be equal, you need to override the == operator in the Point class. For example:

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


  @override
  operator ==(o) => o is Point && o.x == x && o.y == y;
}

void main() {
  var p1 = Point(x: 10, y: 20);
  var p2 = Point(x: 10, y: 20);
  var result = p1 == p2;
  print(result);
}Code language: JavaScript (javascript)

Output:

trueCode language: JavaScript (javascript)

In this example, the operator == returns true if two objects are the instances of the Point class and have the same x and y values.

All Dart classes have a getter hashCode. By rules, if two objects are equal, their hash codes (or values) should be equal. As a developer, you need to preserve this rule.

In practice, if you override the == operator, you should also override the hashCode getter because they’re interrelated.

To calculate the hash of multiple values, you can use the Object.hash() static method. For example, the following Point class overrides both the == operator and hashCode getter:

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

  @override
  operator ==(o) => o is Point && o.x == x && o.y == y;

  @override
  int get hashCode => Object.hash(x, y);  
}

void main() {
  var p1 = Point(x: 10, y: 20);
  var p2 = Point(x: 10, y: 20);
  var result = p1 == p2;
  print(result);
  print('p1: ${p1.hashCode}, p2: ${p2.hashCode}');
}Code language: JavaScript (javascript)

Output:

true
p1: 68682774, p2: 68682774Code language: JavaScript (javascript)

Summary

  • By default, the == operator returns true if two variables reference the same object. It compares objects by their identities.
  • Use the identical() function to check if two objects are the same.
  • Override the == operator to implement custom logic for checking object equality.
  • If two objects are equal, their hash code should be equal. Therefore, you should also override the hashCode getter when overriding the == operator.
Was this tutorial helpful ?