☃️

freezedのオブジェクトの `==` による等価比較

2022/04/19に公開

dart ではこういう等価比較をした場合にオブジェクトが同じかを比較する(==hashCode が override されていなければ)。

class Item {
  Item({ required this.name });
  final String name;
}

void main() {
  final item1 = Item(name: 'a');
  final item2 = Item(name: 'a');
  print(item1 == item2); // falseになる
}

これが @freezed のクラスだと kotlin の data class っぽい挙動となり、異なるオブジェクト同士の == でも各プロパティが一致していれば、等価扱いとなる。


class FreezedItem with _$FreezedItem {
  const FreezedItem._();

  factory FreezedItem({
    required String name,
  }) = _FreezedItem;
}

void main() {
  final item1 = FreezedItem(name: 'a');
  final item2 = FreezedItem(name: 'a');
  print(item1 == item2); // trueになる
}

これに関しては、freezedのドキュメントにも下記のように言及されており、

  • a default ==/toString implementation which respectively compares/shows all properties of the object

自動生成コードを見ても下記のような実装がされているためである。

  
  bool operator ==(dynamic other) {
    return identical(this, other) ||
        (other.runtimeType == runtimeType &&
            other is _FreezedItem &&
            const DeepCollectionEquality().equals(other.name, name));
  }
  
  
  int get hashCode =>
      Object.hash(runtimeType, const DeepCollectionEquality().hash(name));

こういうときにオブジェクト同士を比較したい場合は identicalメソッド で比較する。


class FreezedItem with _$FreezedItem {
  const FreezedItem._();

  factory FreezedItem({
    required String name,
  }) = _FreezedItem;
}

void main() {
  final item1 = FreezedItem(name: 'a');
  final item2 = FreezedItem(name: 'a');
  final item3 = item2;
  print(item1 == item2); // trueになる
  print(identical(item1, item2)); // falseになる
  print(identical(item2, item3)); // trueになる
}

Discussion