Ответ
В Dart все классы неявно наследуются от встроенного класса Object. Это означает, что любой экземпляр любого класса имеет набор базовых методов, определенных в Object.
Основные унаследованные члены:
String toString()— возвращает строковое представление объекта. По умолчанию выводит что-то вродеInstance of 'Person'. Я часто переопределяю его для отладки.int get hashCode— возвращает целочисленный хэш-код объекта, используемый в коллекциях вродеHashMapиHashSet.bool operator ==(Object other)— оператор равенства. Важнейший момент: по умолчанию он сравнивает ссылки (эквивалентноidentical(this, other)), а не содержимое объектов.Type get runtimeType— возвращает тип объекта во время выполнения (runtime).
Критическая связь между == и hashCode:
Если вы переопределяете operator ==, вы обязаны также переопределить hashCode. Объекты, которые равны по ==, должны возвращать одинаковый хэш-код. Нарушение этого контракта приведет к некорректной работе хэш-коллекций.
Пример переопределения в классе модели данных Flutter:
class User {
final String id;
final String name;
const User({required this.id, required this.name});
@override
bool operator ==(Object other) {
// Проверка идентичности ссылок (оптимизация)
if (identical(this, other)) return true;
// Проверка типа и сравнение значимых полей
return other is User &&
runtimeType == other.runtimeType &&
id == other.id; // Сравниваем только id, так как он уникален
}
@override
int get hashCode => id.hashCode; // Хэш-код должен зависеть от тех же полей, что и ==
@override
String toString() => 'User(id: $id, name: $name)'; // Удобно для логов
}
void main() {
final user1 = User(id: '1', name: 'Alice');
final user2 = User(id: '1', name: 'Alice');
final user3 = User(id: '2', name: 'Alice');
print(user1 == user2); // true (id одинаковые)
print(user1 == user3); // false (id разные)
// Благодаря правильному hashCode, объекты корректно работают в Set
final usersSet = {user1, user2, user3};
print(usersSet.length); // 2 (user1 и user3, user2 не добавится, так как равен user1)
}
Понимание этого механизма фундаментально для корректной работы с коллекциями, такими как Set и ключами Map, а также для написания тестов с expect().