假设我有一个具有许多实例变量的类。我想重载 == 运算符(和 hashCode),以便我可以使用实例作为映射中的键。
class Foo {
int a;
int b;
SomeClass c;
SomeOtherClass d;
// etc.
bool operator==(Foo other) {
// Long calculation involving a, b, c, d etc.
}
}
比较计算可能会很昂贵,所以我想在进行计算之前检查
other
是否与 this
是同一实例。
如何调用 Object 类提供的 == 运算符来执行此操作?
您正在寻找“identical”,它将检查两个实例是否相同。
identical(this, other);
更详细的例子?
class Person {
String ssn;
String name;
Person(this.ssn, this.name);
// Define that two persons are equal if their SSNs are equal
bool operator ==(Person other) {
return (other.ssn == ssn);
}
}
main() {
var bob = new Person('111', 'Bob');
var robert = new Person('111', 'Robert');
print(bob == robert); // true
print(identical(bob, robert)); // false, because these are two different instances
}
class Foo{
String uid;
bool isActiv;
Foo(this.uid, this.isActiv){}
Map<String, dynamic> toJson() => _$FooToJson(this);
}
Foo A = Foo("alpha", true);
Foo B = Foo("alpha", true);
print(A.toJson().toString() == B.toJson().toString()); // true
B.uid = "beta";
print(A.toJson().toString() == B.toJson().toString()); // false
Equatable库
class Foo extends EquatableMixin{
int? a;
int? b;
SomeClass? c;
SomeOtherClass? d;
Foo(this.a,this.b,this.c,this.d);
// this does the job, it overrides the hashcode and equals operator
// give all properties to this `props`
@override
List<Object> get props => [a,b,c,d];
}
class SomeOtherClass with EquatableMixin{
String name;
SomeOtherClass(this.name);
@override
List<Object> get props => [name];
}
class SomeClass with EquatableMixin{
String name;
SomeClass(this.name);
@override
List<Object> get props => [name];
}
Foo foo =
Foo(1,2,SomeOtherClass("roger"),SomeOtherClassObject("mack"));
Foo foo2 =
Foo(1,2,SomeOtherClass("roger"),SomeOtherClassObject("mack"));
print(foo == foo2) // prints true
所以,我们不需要手动重写 ==
和
hashcode()
方法 图书馆会这么做的。
注意:内部对象(SomeClass 和 SomeOtherClass)也应该使用 EquatableMixin,我们也可以扩展它或用作 mixin
address 或 hashCode 来比较它们,如下面的代码。
class Foo {
final int a;
final int b;
final SomeClass c;
const Foo({required this.a, required this.b, required this.c});
}
class SomeClass {
final List values;
const SomeClass(this.values);
}
void main() {
const foo1 = Foo(a: 1, b: 1, c: SomeClass([]));
const foo2 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo3 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo4 = Foo(a: 1, b: 1, c: SomeClass([]));
print(foo1 == foo2); // true
print(foo3 == foo4); //false
print(foo1.hashCode == foo2.hashCode); // true
print(foo3.hashCode == foo4.hashCode); // false
}
但是我们有一个大问题,我们可以将常量分配给在编译时定义的变量,但我们不能在运行时执行此操作,请参阅下面的解决方案:)解决方案1:
void main() {
const foo1 = Foo(a: 1, b: 1, c: SomeClass([]));
const foo2 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo3 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo4 = Foo(a: 1, b: 1, c: SomeClass([]));
print(foo1 == foo2); // true
print(foo3 == foo4); //true
print(foo1.hashCode == foo2.hashCode); // true
print(foo3.hashCode == foo4.hashCode); // true
}
class Foo {
final int a;
final int b;
final SomeClass c;
const Foo({required this.a, required this.b, required this.c});
@override
int get hashCode => Object.hash(a.hashCode, b.hashCode, c.hashCode);
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is Foo &&
runtimeType == other.runtimeType &&
hashCode == other.hashCode;
}
}
class SomeClass {
final List values;
const SomeClass(this.values);
@override
int get hashCode => Object.hashAll(values);
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is Foo &&
runtimeType == other.runtimeType &&
hashCode == other.hashCode;
}
}
解决方案2Equtable包
void main() {
const foo1 = Foo(a: 1, b: 1, c: SomeClass([]));
const foo2 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo3 = Foo(a: 1, b: 1, c: SomeClass([]));
final foo4 = Foo(a: 1, b: 1, c: SomeClass([]));
print(foo1 == foo2); // true
print(foo3 == foo4); //true
print(foo1.hashCode == foo2.hashCode); // true
print(foo3.hashCode == foo4.hashCode); // true
}
class Foo extends Equatable {
final int a;
final int b;
final SomeClass c;
const Foo({required this.a, required this.b, required this.c});
@override
List<Object?> get props => [a, b, c];
}
class SomeClass extends Equatable {
final List values;
const SomeClass(this.values);
@override
List<Object?> get props => [values];
}
来源:https://www.youtube.com/watch?v=DCKaFaU4jdk
https://api.flutter.dev/flutter/dart-core/Object/hashCode.html
list.toSet()
从列表中获取唯一元素,则
identical(this, other)
可能不是一个选择。那时该类必须重写
== operator
和
hasCode()
方法。但是对于这种情况,另一种方法可能是使用
equatable 包。这可以节省大量样板代码,当您有很多模型类时特别方便。
final a = SomeClass();
final b = SomeClass();
// Copy one to the other.
b.fromJson(a.toJson());
// Identical properties but not the same object.
a.toString() == b.toString(); // true