Dart中修改对象实例同步变更原对象?如何生成独立可编辑副本
Dart中对象默认按引用传递,直接获取到的实例和原存储的实例指向同一块内存空间,修改会同步生效。要得到独立副本需要实现深拷贝,最常用的方案是为自定义类实现copyWith方法,逐层生成新的实例,实现代码如下:
1. 给嵌套类实现copyWith方法
首先给最内层的Bar类添加拷贝方法:
class Bar{ String name; Bar(this.name); // 生成独立的Bar副本 Bar copyWith({String? name}){ return Bar(name ?? this.name); } }
2. 给外层类实现深拷贝逻辑
Foo类包含自定义类型的列表,拷贝时需要遍历所有嵌套对象生成新实例,不能直接复用原列表:
class Foo{ String name; List<Bar> bars; Foo({required this.name, required this.bars}); // 生成完全独立的Foo副本 Foo copyWith({ String? name, List<Bar>? bars, }){ return Foo( name: name ?? this.name, // 遍历原bars列表,每个元素都生成新实例,放到新列表中 bars: bars ?? this.bars.map((bar) => bar.copyWith()).toList(), ); } }
3. 新增替换原对象的方法
在Manage类中新增更新方法,后续确认修改后可以主动替换原对象:
extension ExtendFoo on Foo{ void addBar(String barName){ this.bars.add(Bar(barName)); } } class Manage{ final List<Foo> _fooList = [ Foo(name : 'foo1', bars: [Bar('bar1'),Bar('bar2')]), Foo(name : 'foo2', bars: [Bar('bar21'),Bar('bar22')]), Foo(name : 'foo3', bars: [Bar('bar31'),Bar('bar32')]), ]; List<Foo> get fooList => _fooList; Foo getFoo(String fooName){ return _fooList.firstWhere((foo)=> foo.name == fooName); } // 用修改后的副本替换原对象的方法 void updateFoo(Foo newFoo){ final index = _fooList.indexWhere((foo) => foo.name == newFoo.name); if(index != -1){ _fooList[index] = newFoo; } } }
4. 调用示例
void main() { Manage manage = Manage(); // 调用copyWith拿到独立副本,修改不会影响原对象 Foo editFoo = manage.getFoo('foo2').copyWith(); editFoo.addBar('newBar'); editFoo.name = 'newName'; // 验证原对象未被修改 print(manage.getFoo('foo2').name); // 输出:foo2 print(manage.getFoo('foo2').bars.length); // 输出:2 // 确认修改无误后,主动调用方法替换原对象 manage.updateFoo(editFoo); // 替换后原存储的对象才会更新 print(manage.getFoo('newName').name); // 输出:newName print(manage.getFoo('newName').bars.length); // 输出:3 }
注意事项
如果类中还有其他嵌套的自定义类型,都需要对应实现copyWith方法逐层拷贝,才能保证副本完全独立不受原对象影响。
内容的提问来源于stack exchange,提问作者Chris Laurie
相关产品推荐
相关产品推荐

