如何在Dart 2中克隆(复制值)复杂对象

时间:2018-07-15 22:17:17

标签: dart

我想使用Dart 2克隆一个复杂的对象(复制值),而不是引用。

示例:

class Person {
  String name;
  String surname;
  City city;
}

class City {
  String name;
  String state;
}

main List<String> args {
  City c1 = new City()..name = 'Blum'..state = 'SC';
  Person p1 = new Person()..name = 'John'..surname = 'Xuebl'..city = c1;


  Person p2 = // HERE, to clone/copy values... Something similar to p1.clone();
}

这样做的最佳方式是什么?(最佳做法)?

更新说明:此How can I clone an Object (deep copy) in Dart?是在一段时间之前发布的。这里的重点是了解进行了许多改进的Dart 2是否具有复制复杂对象的功能。

4 个答案:

答案 0 :(得分:1)

有了您在这里向我们展示的课程,没有什么比

Person p2 = Person()
  ..name = p1.name
  ..surname = p1.surname
  ..city = (City()..name = p1.city.name..state = p1.city.state);

如果将clone方法添加到PersonCity,那么显然可以使用它。 该语言没有内置功能可让您复制对象的状态。

我建议至少通过添加构造函数来更改类:

class Person {
  String name;
  String surname;
  City city;
  Person(this.name, this.surname, this.city);
}
class City {
  String name;
  String state;
  City(this.name, this.state);
}

然后您可以通过编写以下内容来克隆:

Person P2 = Person(p1.name, p1.surname, City(p1.city.name, p1.city.state));

(还有ob-link的名字)

我说没有复制对象的语言功能,但是实际上,如果您可以访问dart:isolate库,则存在复制对象的功能:通过隔离的通信端口发送对象。我不建议您使用该功能,但这是为了完整性:

import "dart:isolate";
Future<T> clone<T>(T object) {
  var c = Completer<T>();
  var port = RawReceivePort();
  port.handler = (Object o) {
    port.close();
    c.complete(o);
  }
  return c.future;
}

同样,我不建议您使用这种方法。 它适用于像这样的简单对象,但不适用于所有对象(并非所有对象都可以通过通信端口发送,例如,一等函数或任何包含一等函数的对象)。

编写类以支持所需的操作,包括复制。

答案 1 :(得分:1)

如前所述,没有内置的解决方案,但是如果要实现不可变的值类型,则可以选中built_value

https://medium.com/dartlang/darts-built-value-for-immutable-object-models-83e2497922d4

答案 2 :(得分:0)

我注意到使用Map.from() 进行浅拷贝而不是深拷贝

要对包含注释类的Map的类进行深层复制,一种解决方案是使用命名的构造函数

class MyClassB {
   int myVar;
   
   // Constructor
   MyClassB(this.id);
   
   // Named Constructor to do a deep clone
   MyClassB.clone(MyClassB b){
     id = b.id;
   }
}

class MyClassA { 
  Map<int,MyClassB> mapOfClassB;

  // Constructor
  MyClassA(this.myClassB)

  // Named constructor to do a deep clone
  MyClassA.clone(MyClassA a){
    Map<int,myClassB> m = {};
    myClassB  = a.mapOfClassB.forEach((k,v)=> m[k] = MyClassB.clone(v)); // Use the clone constructor here, if not the maps in MyClassA and MyClassB will linked
  }
}

main() {
  var b1 = MyClassB(20);
  var a1 = MyClassA({0:b1});
  
  var a2 = MyClass1A.clone(a1);
  
  a2.mapOfClassB[0].id = 50;
  
  print(a1.mapOfClassB[0].id); // Should display 20
  print(a2.(a1.mapOfClassB[0].id) // Should display 50 
}

答案 3 :(得分:0)

我的更简单解决方案只是让clone()返回具有当前值的新Person

class Person {
  String name;
  String surname;
  City city;
  Person(this.name, this.surname, this.city);
  clone() => Person(name, surname, city);
}

您可能还需要递归地克隆Person中的对象。例如,通过在clone()中创建类似的City函数并将其在此处用作city.clone()
对于字符串,您将需要检查其行为或创建/添加一种清理它们的方法。

相关问题