Dart/Flutter 不使用Equatable时如何判断两个对象是否逻辑等价
Dart类实例深度属性比较实现方案
不需要依赖Equatable包,也无需将属性标记为final,以下是两种常用落地实现:
方案1:手动逐字段对比(性能最优)
直接在类中自定义比较方法,按需实现基础类型、集合类型、自定义类型的深度对比,适合字段数量较少的类:
class User { // 无需标记为final String name; int age; List<String> tags; User({required this.name, required this.age, required this.tags}); /// 深度比较两个实例属性是否完全一致 bool isEqualTo(User other) { // 基础类型字段直接对比 if (name != other.name || age != other.age) return false; // 集合类字段深度对比 if (tags.length != other.tags.length) return false; for (int i = 0; i < tags.length; i++) { if (tags[i] != other.tags[i]) return false; } // 有自定义类属性的话,对应调用自定义类的比较方法即可 // if (!customAttr.isEqualTo(other.customAttr)) return false; return true; } } // 调用示例 void main() { final userA = User(name: "张三", age: 20, tags: ["学生", "男性"]); final userB = User(name: "张三", age: 20, tags: ["学生", "男性"]); print(userA.isEqualTo(userB)); // 输出 true print(identical(userA, userB)); // 输出 false,不会判定为同一个内存实例 }
方案2:JSON序列化对比(开发效率最高)
如果类字段多、嵌套结构复杂,手动写对比逻辑成本高,可以通过序列化JSON字符串对比的方式实现,只要维护类的toJson方法即可:
import 'dart:convert'; class User { String name; int age; List<String> tags; User({required this.name, required this.age, required this.tags}); Map<String, dynamic> toJson() => { "name": name, "age": age, "tags": tags, // 嵌套自定义类也要实现toJson方法 // "customAttr": customAttr.toJson(), }; bool isEqualTo(User other) { return jsonEncode(this) == jsonEncode(other); } }
这种方案的优势是代码量少,嵌套结构适配成本低,普通业务场景性能足够,缺点是对比效率低于手动实现的方案。
注意事项
- 两种方案都只会校验属性值的逻辑等价性,不会判断两个实例是否为同一个内存对象
- 如果属性包含自定义类,需要给对应的自定义类也实现比较逻辑(方案1)或
toJson方法(方案2),才能保证深度比较完全生效
内容的提问来源于stack exchange,提问作者kris
相关产品推荐
相关产品推荐

