Understanding the difference between deep and shallow copying
When you create a collection in Dart, the contents of the collection are mutable. You can see that in the following example:
final myList = ['sheep', 'cow'];
myList.add('horse'); // [sheep, cow, horse]
myList.remove('cow'); // [sheep, horse]
myList[0] = 'goat'; // [goat, horse]
That is all very useful when you want to manipulate the elements of a collection. However, sometimes you want to share a copy of your collection with someone else.
Let’s look at what happens when you “copy” a list by assigning it to a new variable:
final myList = ['sheep', 'cow'];
final yourCopy = myList;
yourCopy.remove('cow');print(myList); // [sheep]
print(yourCopy); // [sheep]
You removed “your” cow, by now mine is gone, too!
The reason is that all variable names in Dart are just references that ultimately lead to where the object is stored in memory. Assigning one variable name to another copies the reference; it doesn’t make a new copy of the object itself. If I write my email address and password on a piece of paper and give it to you, that doesn’t create a new email account for you; it just gives you access to my account. Dart objects are the same way; assigning one variable to another is just copying the address, not the value itself.
For simple types like String
, int
, and double
, there is no need for concern because they’re all immutable. You can’t change anything about them, so you don’t have to worry about someone else messing with your values. Here’s an example:
final myString = 'goat';
var yourCopy = myString;
yourCopy = 'camel';print(myString); // goat
print(yourCopy); // camel
myString
is a reference to some location in memory that’s storing the 'goat'
object. When you assign myString
to yourCopy
, now yourCopy
is also referring to the 'goat'
object in memory. However, when you set yourCopy
to 'camel'
, this creates a whole new object at a different location in memory. It doesn’t mutate 'goat'
. It can’t mutate 'goat'
because strings are immutable. So when you print myString
and yourCopy
, they print different values because…