【Dart】オブジェクトをコピーするcopyWithの基本

2 min read読了の目安(約2100字

【Dart】オブジェクトのコピー

普通にB = Aでコピーする(失敗例)

  • hashCodeで同一性を確認(メモリ上のアドレスも同一か)したところ、同一
    • =同じものを指すオブジェクトが二つ生まれた
class User {
  final String username;

  const User({this.username});
}

void main() {
  const userA = User(username: 'UserA');

  const userB = userA;
  print(userA.username + ':' + userA.hashCode.toString());
  print(userB.username + ':' + userA.hashCode.toString());
}

実行結果

UserA:419201198
UserA:419201198
  • 【備考】確認の出力関数toString()を、Userクラスに追加
class User {
  final String username;

  const User({this.username});

  
  String toString() => username + ':' + hashCode.toString();
}

void main() {
  const userA = User(username: 'UserA');

  const userB = userA;
  print(userA.toString());
  print(userB.username + ':' + userA.hashCode.toString());
}

実行結果

UserA:288318752
UserA:288318752
  • 【備考】userBはconstではなくfinalの場合も同様
class User {
  final String username;

  const User({this.username});

  User copyWith({
    String username,
  }) =>
      User(
        username: username ?? this.username,
      );

  
  String toString() => username + ':' + hashCode.toString();
}

void main() {
  const userA = User(username: 'UserA');
  final userB = userA;
  print(userA.toString());
  print(userB.toString());
}

実行結果

UserA:463513894
UserA:463513894

copyWith関数利用(成功例)

  • copyWithを追加し、利用すると別のオブジェクトとする
    • copyWithへの引数がなければ、コピー元の値が利用される
    • 【備考】const userB = userA.copyWith();だと以下エラーとなる
      • Const variables must be initialized with a constant value
class User {
  final String username;

  const User({this.username});

  User copyWith({
    String username,
  }) =>
      User(
        username: username ?? this.username,
      );

  
  String toString() => username + ':' + hashCode.toString();
}

void main() {
  const userA = User(username: 'UserA');
  final userB = userA.copyWith();
  final userC = userA.copyWith(username: 'UserC');
  print(userA.toString());
  print(userB.toString());
  print(userC.toString());
}

実行結果

UserA:610790447
UserA:455007180
UserC:1059822335