avoid-equals-and-hash-code-on-mutable-classes
Same as avoid_equals_and_hash_code_on_mutable_classes in Dart lints
- Group
- Style
- Path
lint/style/avoid-equals-and-hash-code-on-mutable-classes- Default
- Off, opt in
- Origin
- Dart lints
- Rule
- 62 of 512
Flags == and hashCode overrides in classes not marked @immutable.
A value-based == and hashCode on a mutable object is a trap: once the
object is stored in a Set or used as a Map key, mutating it changes its
hash code and the collection silently loses track of it. Only classes that
are (transitively) annotated with package:meta's @immutable should
override them.
The diagnostic covers the first declaration token after metadata.
class Point { // not @immutable
int x;
Point(this.x);
@override
bool operator ==(Object other) => other is Point && other.x == x; // flagged
@override
int get hashCode => x.hashCode; // flagged
}
The annotation may sit on the class itself or on any supertype (superclass, mixin, or interface). Unresolved supertypes leave immutability unknown.
Invalid
import 'package:meta/meta.dart';
class Point {
int x;
Point(this.x);
@override
bool operator ==(Object other) => other is Point && other.x == x;
@override
int get hashCode => x.hashCode;
}
class Name {
final String value;
Name(this.value);
@override
bool operator ==(Object other) => other is Name && other.value == value;
}
class Id {
final int id;
Id(this.id);
@override
int get hashCode => id;
}
// A non-immutable superclass does not make the subclass immutable.
class Base {}
class Derived extends Base {
@override
bool operator ==(Object other) => identical(this, other);
}
mixin class Tagged {
@override
int get hashCode => 7;
}
// `@immutable` on an unrelated declaration does not apply.
@immutable
class Frozen {
const Frozen();
}
class Unrelated {
@override
bool operator ==(Object other) => other is Unrelated;
}
// SDK supertypes never carry `@immutable`.
class Ordered implements Comparable<Ordered> {
int value = 0;
@override
int compareTo(Ordered other) => 0;
@override
bool operator ==(Object other) => other is Ordered && other.value == value;
} @override bool operator ==(Object other) => other is Point && other.x == x; @override int get hashCode => x.hashCode; @override bool operator ==(Object other) => other is Name && other.value == value; @override int get hashCode => id; @override bool operator ==(Object other) => identical(this, other); @override int get hashCode => 7; @override bool operator ==(Object other) => other is Unrelated; @override bool operator ==(Object other) => other is Ordered && other.value == value;Valid
import 'package:meta/meta.dart';
import 'package:meta/meta.dart' as m;
@immutable
class Point {
final int x;
const Point(this.x);
@override
bool operator ==(Object other) => other is Point && other.x == x;
@override
int get hashCode => x.hashCode;
}
// Immutability is inherited from an annotated supertype.
@immutable
abstract class Value {
const Value();
}
class Meters extends Value {
final double meters;
const Meters(this.meters);
@override
bool operator ==(Object other) => other is Meters && other.meters == meters;
@override
int get hashCode => meters.hashCode;
}
class Kilometers implements Value {
final double km;
const Kilometers(this.km);
@override
bool operator ==(Object other) => other is Kilometers && other.km == km;
@override
int get hashCode => km.hashCode;
}
// Mutable classes that keep identity equality are fine.
class Counter {
int count = 0;
void increment() => count++;
}
// Other operators are not reported.
class Vector {
int x = 0;
Vector operator +(Vector other) => Vector()..x = x + other.x;
}
// Extensions cannot override `==`; enums cannot either.
enum Mode { on, off }
@m.Immutable('x')
class ImmutableReason {
@override
bool operator ==(Object other) => true;
}
@Immutable()
class ImmutableConstructor {
@override
int get hashCode => 0;
}Configure avoid-equals-and-hash-code-on-mutable-classes
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"style": {
"avoid-equals-and-hash-code-on-mutable-classes": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/style/avoid-equals-and-hash-code-on-mutable-classes: <reason>More style rules
- avoid-escaping-inner-quotes
avoid_escaping_inner_quotesFlags a string literal that escapes its own quote character when switching the outer quotes would remove every escape.
- avoid-field-initializers-in-const-classes
avoid_field_initializers_in_const_classesFlags field initializers in classes with a
constconstructor. - avoid-final-parameters
avoid_final_parametersFlags parameters declared
final. - avoid-implementing-value-types
avoid_implementing_value_typesFlags
implementsof a class that overrides==. - avoid-init-to-null
avoid_init_to_nullrecommendedFlags explicit
= nullinitializers on declarations that already default to null. - avoid-js-rounded-ints
avoid_js_rounded_intsrecommendedAvoid integer literals that JavaScript would round.
- avoid-late-keyword
avoid-late-keywordFlags use of the
latekeyword on variables and fields. - avoid-multiple-declarations-per-line
avoid_multiple_declarations_per_linerecommendedFlags a variable declaration that declares more than one variable.