Scorb
Scorb

Reputation: 1870

Override `==` if overriding `hashCode`

I have the following class in dart...

class Color {
    final int value;
    const Color._internal(this.value);

    static const Color WHITE = const Color._internal(0);
    static const Color BLACK = const Color._internal(1);

    int get hashCode => value;
    String toString() => (this == WHITE) ? 'w' : 'b';
}

When I run the flutter analyze command I get the following error...

info • Override == if overriding hashCode • lib/chess.dart:1584:13 • hash_and_equals

As a test I added the method

bool operator==(Object o) => true;

But then I got another analyzer problem....

error • The constant map entry key expression type 'Color' can't override the == operator • lib/chess.dart:44:3 • const_map_key_expression_type_implements_equals

This is because the Color object is used as a key in a static const map...

static const Map<Color, List> PAWN_OFFSETS = const {
    BLACK: const [16, 32, 17, 15],
    WHITE: const [-16, -32, -17, -15]
};

So I am confused as to what my options are to prevent these analyzer issues.

If I remove the hashCode, the class wont work in a map... If I add the == operator I just get a different error.

What is the best option?

Upvotes: 6

Views: 3946

Answers (2)

Ryan Deschamps
Ryan Deschamps

Reputation: 385

The issue is that Dart will need to assess the const Map during compile time. Since you have a user-generated object, it cannot do that, thus the error.

Your choices are:

  1. Make your map non-const. You can use bool operator ==(Object o) => trueif you wish, but proper style suggests over-riding both hashCode and == at the same time.
  2. Do not use the override and use Color.value to pass through a const map<int, List> instead.

The following GIST shows option 1 in DartPad. The following issue in Flutter's Github helped me with the answer.

Upvotes: 3

drogel
drogel

Reputation: 2717

You cannot have two equal keys in a Map, and you are telling the compiler that any Color object is equal to any other Color object by stating:

bool operator==(Object o) => true;

This way, the compiler thinks BLACK and WHITE are the same thing. However, if you do something like this instead:

bool operator==(Object o) => o is Color && o.value == value;

the compiler will only consider two Color objects equal if their values are equal. Therefore, it won't consider BLACK and WHITE to be equal anymore (since their values are different), and the issue should be solved.

Upvotes: -1

Related Questions