102

Dartでオブジェクトの完全な(深い)コピーを作成する言語サポートの方法はありますか?

二次のみ。これを行うには複数の方法がありますか?違いは何ですか?

説明してくれてありがとう!

4

16 に答える 16

51

Dartsの組み込みコレクションは、これを実現するために「from」と呼ばれる名前付きコンストラクターを使用します。この投稿を参照してください:Dartでリスト、マップ、またはセットを複製します

Map mapA = {
    'foo': 'bar'
};
Map mapB = new Map.from(mapA);
于 2015-02-17T03:26:11.783 に答える
37

未解決の問題が示唆しているように思われる限りではありません:

http://code.google.com/p/dart/issues/detail?id=3367

そして具体的には:

.. Objects have identity, and you can only pass around references to them. There is no implicit copying.
于 2012-10-28T10:19:50.627 に答える
27

パーティーに遅れましたが、私は最近この問題に直面し、次のようなことをしなければなりませんでした:-

class RandomObject {

  RandomObject(this.x, this.y);

  RandomObject.clone(RandomObject randomObject): this(randomObject.x, randomObject.y);

  int x;
  int y;
}

次に、次のように、オリジナルでコピーを呼び出すことができます。

final RandomObject original = RandomObject(1, 2);
final RandomObject copy = RandomObject.clone(original);
于 2019-01-10T20:48:09.400 に答える
15

あまり複雑ではないオブジェクトの場合は、変換ライブラリを使用できます。

import 'dart:convert';

次に、JSONのエンコード/デコード機能を使用します

Map clonedObject = JSON.decode(JSON.encode(object));

クローンを作成するオブジェクトの値としてカスタムクラスを使用している場合、クラスはtoJson()メソッドを実装するか、JSON.encodeメソッドにtoEncodable関数を提供し、デコード呼び出しにreviverメソッドを提供する必要があります。 。

于 2014-10-28T18:41:59.070 に答える
9

残念ながら、言語サポートはありません。Copyable私がしたことは、コピーできるようにしたいクラスに実装できるという抽象クラスを作成することです。

abstract class Copyable<T> {
  T copy();
  T copyWith();
}

次に、これを次のように使用できます。たとえば、Locationオブジェクトの場合です。

class Location implements Copyable<Location> {
  Location({
    required this.longitude,
    required this.latitude,
    required this.timestamp,
  });

  final double longitude;
  final double latitude;
  final DateTime timestamp;

  @override
  Location copy() => Location(
        longitude: longitude,
        latitude: latitude,
        timestamp: timestamp,
      );

  @override
  Location copyWith({
    double? longitude,
    double? latitude,
    DateTime? timestamp,
  }) =>
      Location(
        longitude: longitude ?? this.longitude,
        latitude: latitude ?? this.latitude,
        timestamp: timestamp ?? this.timestamp,
      );
}
于 2020-03-27T19:32:16.543 に答える
8

参照なしでオブジェクトをコピーするには、私が見つけた解決策はここに投稿されたものと似ていましたが、オブジェクトにMAPまたはLISTが含まれている場合は、次のようにする必要があります。

class Item {
  int id;
  String nome;
  String email;
  bool logado;
  Map mapa;
  List lista;
  Item({this.id, this.nome, this.email, this.logado, this.mapa, this.lista});

  Item copyWith({ int id, String nome, String email, bool logado, Map mapa, List lista }) {
    return Item(
      id: id ?? this.id,
      nome: nome ?? this.nome,
      email: email ?? this.email,
      logado: logado ?? this.logado,
      mapa: mapa ?? Map.from(this.mapa ?? {}),
      lista: lista ?? List.from(this.lista ?? []),
    );
  }
}
Item item1 = Item(
    id: 1,
    nome: 'João Silva',
    email: 'joaosilva@gmail.com',
    logado: true,
    mapa: {
      'chave1': 'valor1',
      'chave2': 'valor2',
    },
    lista: ['1', '2'],
  );

// -----------------
// copy and change data
Item item2 = item1.copyWith(
    id: 2,
    nome: 'Pedro de Nobrega',
    lista: ['4', '5', '6', '7', '8']
  );

// -----------------
// copy and not change data
Item item3 = item1.copyWith();

// -----------------
// copy and change a specific key of Map or List
Item item4 = item1.copyWith();
item4.mapa['chave2'] = 'valor2New';

ダートパッドの例を見る

https://dartpad.dev/f114ef18700a41a3aa04a4837c13c70e

于 2020-05-30T02:24:04.650 に答える
5

あなたがクラスを持っているとしましょう

Class DailyInfo

  { 
     String xxx;
  }

クラスオブジェクトdailyInfoの新しいクローンを作成します。

 DailyInfo newDailyInfo =  new DailyInfo.fromJson(dailyInfo.toJson());

これが機能するには、クラスが実装されている必要があります

 factory DailyInfo.fromJson(Map<String, dynamic> json) => _$DailyInfoFromJson(json);


Map<String, dynamic> toJson() => _$DailyInfoToJson(this);

これは、を使用してクラスをシリアル化可能にすることで実行できます。

@JsonSerializable(fieldRename: FieldRename.snake, includeIfNull: false)
Class DailyInfo{ 
 String xxx;
}
于 2019-07-25T17:30:07.093 に答える
4

JSONで表現できるオブジェクトタイプに対してのみ機能します。

ClassName newObj = ClassName.fromMap(obj.toMap());

また

ClassName newObj = ClassName.fromJson(obj.toJson());
于 2020-01-17T08:02:29.067 に答える
4

Dartが提供するコピー可能なインターフェースを使用してみてください。

于 2020-01-22T01:34:12.167 に答える
3

オブジェクトをディープクローンする組み込みの方法はありません。オブジェクトのメソッドを自分で提供する必要があります。

私はJSONからクラスをエンコード/デコードする必要があることが多いので、通常はメソッドを提供MyClass fromMap(Map)Map<String, dynamic> toJson()ます。これらを使用して、最初にオブジェクトをJSONにエンコードし、次にデコードして戻すことで、ディープクローンを作成できます。

ただし、パフォーマンス上の理由から、通常はclone代わりに別のメソッドを実装します。数分の作業ですが、よく費やされることが多いようです。

以下の例でcloneSlowは、JSON手法をcloneFast使用し、明示的に実装されたクローンメソッドを使用しています。プリントアウトは、クローンが実際にはディープクローンであり、への参照の単なるコピーではないことを証明しaます。

import 'dart:convert';

class A{
  String a;
  A(this.a);
  
  factory A.fromMap(Map map){
    return A(
        map['a']
   );
  }
  
  Map<String, dynamic> toJson(){
    return {
      'a': a
    };
  }
  
  
  A cloneSlow(){
    return A.fromMap(jsonDecode(jsonEncode(this)));
  }

  A cloneFast(){
    return A(
      a
    );
  }
  
  
  @override
  String toString() => 'A(a: $a)';
}

void main() {
  A a = A('a');
  A b = a.cloneFast();
  b.a = 'b';
  
  print('a: $a   b: $b');
}




于 2020-12-30T09:07:39.770 に答える
2

この問題を解決する簡単な方法は、...たとえば演算子を使用するだけです。たとえば、マップのクローンを作成します。

Map p = {'name' : 'parsa','age' : 27};
Map n = {...p};

また、クラスプロパティに対してこれを行うことができます。私の場合、クラスのリストされたプロパティのクローンを作成する必要がありました。それで:

class P1 {
List<String> names = [some data];
}

/// codes
P1 p = P1();
List<String> clonedList = [...p.names]
// now clonedList is an unreferenced type
于 2021-11-10T14:16:29.767 に答える
1

//この作品を願っています

 void main() {
  List newList = [{"top": 179.399, "left": 384.5, "bottom": 362.6, "right": 1534.5}, {"top": 384.4, "left": 656.5, "bottom": 574.6, "right": 1264.5}];
  List tempList = cloneMyList(newList);
  tempList[0]["top"] = 100;
  newList[1]["left"] = 300;
  print(newList);
  print(tempList);
}

List cloneMyList(List originalList) {
 List clonedList = new List();
  for(Map data in originalList) {
    clonedList.add(Map.from(data));
  }
  return clonedList;
}
于 2020-12-07T08:44:28.553 に答える
1

@Phill Wigginsの回答を参照して、.fromコンストラクターと名前付きパラメーターを使用した例を次に示します。

class SomeObject{
  String parameter1;
  String parameter2;

  // Normal Constructor
  SomeObject({
    this.parameter1,
    this.parameter2,
  });

  // .from Constructor for copying
  factory SomeObject.from(SomeObject objectA){
    return SomeObject(
      parameter1: objectA.parameter1,
      parameter2: objectA.parameter2,
    );
  }

}

次に、コピーする場所でこれを実行します。

SomeObject a = SomeObject(parameter1: "param1", parameter2: "param2");
SomeObject copyOfA = SomeObject.from(a);
于 2021-05-28T10:00:58.833 に答える
0

ダーツのディープコピーの例。

void main() {
  Person person1 = Person(
      id: 1001,
      firstName: 'John',
      lastName: 'Doe',
      email: 'john.doe@email.com',
      alive: true);

  Person person2 = Person(
      id: person1.id,
      firstName: person1.firstName,
      lastName: person1.lastName,
      email: person1.email,
      alive: person1.alive);

  print('Object: person1');
  print('id     : ${person1.id}');
  print('fName  : ${person1.firstName}');
  print('lName  : ${person1.lastName}');
  print('email  : ${person1.email}');
  print('alive  : ${person1.alive}');
  print('=hashCode=: ${person1.hashCode}');

  print('Object: person2');
  print('id     : ${person2.id}');
  print('fName  : ${person2.firstName}');
  print('lName  : ${person2.lastName}');
  print('email  : ${person2.email}');
  print('alive  : ${person2.alive}');
  print('=hashCode=: ${person2.hashCode}');
}

class Person {
  int id;
  String firstName;
  String lastName;
  String email;
  bool alive;
  Person({this.id, this.firstName, this.lastName, this.email, this.alive});
}

そして、以下の出力。

id     : 1001
fName  : John
lName  : Doe
email  : john.doe@email.com
alive  : true
=hashCode=: 515186678

Object: person2
id     : 1001
fName  : John
lName  : Doe
email  : john.doe@email.com
alive  : true
=hashCode=: 686393765
于 2020-11-17T01:45:41.907 に答える
0

ヘルパークラスを作成します。

class DeepCopy {
  static clone(obj) {
    var tempObj = {};
    for (var key in obj.keys) {
      tempObj[key] = obj[key];
    }
    return tempObj;
  }
}

必要なものをコピーします。

 List cloneList = [];
 if (existList.length > 0) {
    for (var element in existList) {
        cloneList.add(DeepCopy.clone(element));
    }
 }
于 2021-01-07T02:40:49.623 に答える
0

Person他のオブジェクトのリストである属性を持つオブジェクトをディープコピーするとしますSkills。慣例により、copyWithディープコピーにはオプションのパラメーターを指定したメソッドを使用しますが、任意の名前を付けることができます。

あなたはこのようなことをすることができます

class Skills {
  final String name;

  Skills({required this.name});

  Skills copyWith({
    String? name,
  }) {
    return Skills(
      name: name ?? this.name,
    );
  }
}

class Person {
  final List<Skills> skills;

  const Person({required this.skills});

  Person copyWith({
    List<Skills>? skills,
  }) =>
      Person(skills: skills ?? this.skills.map((e) => e.copyWith()).toList());
}

onlyを使用するthis.skillsと、リストの参照のみがコピーされることに注意してください。したがって、元のオブジェクトとコピーされたオブジェクトは同じスキルのリストを指します。

  Person copyWith({
    List<Skills>? skills,
  }) =>
      Person(skills: skills ?? this.skills);

リストがプリミティブ型の場合は、次のように実行できます。プリミティブ型は自動的にコピーされるため、この短い構文を使用できます。

class Person {
  final List<int> names;

  const Person({required this.names});

  Person copyWith({
    List<int>? names,
  }) =>
      Person(names: names ?? []...addAll(names));
}
于 2021-08-05T18:39:40.327 に答える