[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 && ...
}
~~~