Почему оператор распространения в 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
});
Чего я пытаюсь добиться, так это иметь возможность изменять вложенные свойства только на одном из клонов.
Оператор 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
}
«Почему оператор распространения в Dart не клонирует вложенные карты?» Dart не имеет конструкторов копирования, и поэтому он не умеет создавать копии произвольных объектов. Возможно, вы могли бы возразить, что
List
,Map
иSet
можно рассматривать как особые случаи, но я думаю, что было бы запутанно, если бы при копировании коллекции копировались одни объекты, а другие — нет.