Equality Design
DO
DO override hashCode if you override ==.
The default hash code implementation provides an identity hash — two objects generally only have the same hash code if they are the exact same object. Likewise, the default behavior for == is identity.
If you are overriding ==, it implies you may have different objects that are considered “equal” by your class. Any two objects that are equal must have the same hash code. Otherwise, maps and other hash-based collections will fail to recognize that the two objects are equivalent.
DO make your == operator obey the mathematical rules of equality.
An equivalence relation should be:
-
Reflexive:
a == ashould always returntrue. -
Symmetric:
a == bshould return the same thing asb == a. -
Transitive: If
a == bandb == cboth returntrue, thena == cshould too.
Users and code that uses == expect all of these laws to be followed. If your class can’t obey these rules, then == isn’t the right name for the operation you’re trying to express.
AVOID
AVOID defining custom equality for mutable classes.
When you define ==, you also have to define hashCode. Both of those should take into account the object’s fields. If those fields change then that implies the object’s hash code can change.
Most hash-based collections don’t anticipate that—they assume an object’s hash code will be the same forever and may behave unpredictably if that isn’t true.
DON'T
DON’T check for null in custom == operators.
The language specifies that this check is done automatically and your == method is called only if the right-hand side is not null.
class Person {
final String name;
// ···
bool operator ==(other) => other is Person && name == other.name;
int get hashCode => name.hashCode;
}
class Person {
final String name;
// ···
bool operator ==(other) => other != null && ...
}
Semantic portal