Оператор распространения дротика с вложенной картой

Почему оператор распространения в Dart не клонирует вложенные карты? Этот пример показывает, что «вложенная» карта на обоих клонах относится к одному и тому же объекту.

    test("test map", () {
      // Define sourceA
      var sourceA = {
        "nested": {
          "value": 10
        }
      };

      // Define sourceB
      var sourceB = {
        "sourceA": {...sourceA}
      };

      // Clone both sources into two new maps
      var m1 = {...sourceA};
      var m2 = {...sourceB};

      print(m2["sourceA"]!["nested"] == m1["nested"]); // prints true

      // Check hash codes
      print(m2["sourceA"]!["nested"].hashCode); // prints 480486640
      print(m1["nested"].hashCode);             // prints 480486640

      // Change the nested value of m2
      m2["sourceA"]!["nested"]!["value"] = 11;

      // Observe it has been changed in m1
      print(m1["nested"]!["value"]); // prints 11
    });

Чего я пытаюсь добиться, так это иметь возможность изменять вложенные свойства только на одном из клонов.

«Почему оператор распространения в Dart не клонирует вложенные карты?» Dart не имеет конструкторов копирования, и поэтому он не умеет создавать копии произвольных объектов. Возможно, вы могли бы возразить, что List, Map и Set можно рассматривать как особые случаи, но я думаю, что было бы запутанно, если бы при копировании коллекции копировались одни объекты, а другие — нет.

jamesdlin 18.03.2022 07:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
26
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оператор Spread копирует коллекцию со своей ссылкой, также известной как Shallow copy. Чтобы узнать больше о различиях между мелким и глубоким копированием, вы можете прочитать статью здесь. Это довольно распространено во многих языках.

Есть разные способы сделать глубокую копию в Dart. Вот пример, основанный на вашем коде:

import 'dart:convert';

main(){
  // Define sourceA
      var sourceA = {
        "nested": {
          "value": 10
        }
      };

      // Define sourceB
      var sourceB = {
        "sourceA": {...sourceA}
      };
  

      // Clone both sources into two new maps
      var m1 = {...sourceA};
      var m2 = {...sourceB};
      var m3 = json.decode(json.encode(sourceB)); // deep copy

      print(m2["sourceA"]!["nested"] == m1["nested"]); // prints true
      print(m3["sourceA"]!["nested"] == m1["nested"]); // prints false

      // Check hash codes
      print(m2["sourceA"]!["nested"].hashCode); // prints 418854379
      print(m3["sourceA"]!["nested"].hashCode); // prints 892131505
      print(m1["nested"].hashCode);             // prints 418854379

      // Change the nested value of m3
      // m2["sourceA"]!["nested"]!["value"] = 11;
      m3["sourceA"]!["nested"]!["value"] = 11;

      // Observe it has been changed in m1
      print(m1["nested"]!["value"]); // prints 10
}

Другие вопросы по теме