如果一个是const,为什么Dart有时会认为对象不相等?

时间:2019-05-08 17:13:16

标签: dart

我有ClassA,其中有一个List<ClassB>ClassB具有字符串属性。

如果我现在有一个ClassA的const对象和一个ClassB对象的列表,它与另一个ClassA non const 对象完全相同,并且与ClassB完全相同的对象,则这两个对象不视为相等。

为什么?在查找有关平等的任何文档时,我找不到任何引用此情况的文档。

代码如下:

import 'package:test/test.dart';

void main() {
  test('equal', () {
    const ClassA a1 = ClassA(list: [ClassB(text: "Mo")]);
    ClassA a2 = ClassA(list: [ClassB(text: "Mo"),]);

    expect(const [ClassB(text: "Mo")], [ClassB(text: "Mo")]);//true
    expect(a1, equals(a2)); //false. Is only true when a2 is const.
  });
}

class ClassB {
  final String text;

  const ClassB({this.text});

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ClassB &&
          runtimeType == other.runtimeType &&
          text == other.text;

  @override
  int get hashCode => text.hashCode;
}

class ClassA {
  final List<ClassB> list;
  const ClassA({this.list});

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ClassA &&
          runtimeType == other.runtimeType &&
          list == other.list;

  @override
  int get hashCode => list.hashCode;
}

我期望a1和a2相等。

1 个答案:

答案 0 :(得分:1)

问题在于listother.list仅当它们都是const时才相等(当然,它们具有相同的const值),因为它们是同一对象。

package:collections有一些有用的比较工具。

您的equals运算符可以重写为:

import 'package:collection/collection.dart';
...  
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ClassA && ListEquality<ClassB>().equals(list, other.list);

您还需要更改hashCode的实现,因为通过上述更改,这些类现在为equal,但具有不同的hashCode。参见下面的编辑...

请参见also

编辑

class ClassA {
  final List<ClassB> list;
  final ListEquality<ClassB> equality = const ListEquality<ClassB>();

  const ClassA({this.list});

  @override
  bool operator ==(Object other) {
    return identical(this, other) ||
      other is ClassA && equality.equals(list, other.list);
  }

  @override
  int get hashCode => equality.hash(list);
}