[TOC]
为类实现自定义相等行为可能很棘手。用户对对象需要匹配的等式如何工作有很深的直觉,而像哈希表这样的集合类型有一些微妙的约定,他们希望元素遵循这些约定。
## 如果您重写==,请重写hashCode。
默认的哈希代码实现提供了一个标识哈希——如果两个对象是完全相同的对象,通常只有相同的哈希代码。同样,==的默认行为是identity。
如果你重写==,这意味着你可能有不同的对象被你的类认为是“相等的”。任何两个相等的对象都必须具有相同的哈希代码。否则,映射和其他基于散列的集合将无法识别这两个对象是等价的。
## 一定要让你的==运算符遵守等式的数学规则。
一个等价关系应该是:
* 条件反射:a == a应该总是返回true。
* 对称的:a == b应该返回与b == a相同的东西。
* 传递式:如果a == b和b == c都返回true,那么a == c也应该返回true。
使用==的用户和代码期望遵循所有这些规则。如果您的类不能遵守这些规则,那么==就不是您要表示的操作的正确名称。
## 避免为可变类定义自定义等式。
在定义==时,还必须定义hashCode。这两个都应该考虑到对象的字段。如果这些字段改变了,那么就意味着对象的哈希代码可以改变。
大多数基于哈希的集合都没有预料到这一点——它们假设一个对象的哈希代码将永远是相同的,如果这不是真的,那么它的行为可能是不可预测的。
## 不要在自定义 ==运算符中检查null。
该语言指定此检查是自动完成的,只有当右侧不为空时才调用您的==方法。
~~~
class Person {
final String name;
// ···
operator ==(other) => other is Person && name == other.name;
int get hashCode => name.hashCode;
}
~~~
~~~
【bad】
class Person {
final String name;
// ···
operator ==(other) => other != null && ...
}
~~~