Deep copy in Ruby

Tram Ho

Copying values ​​in Ruby is often necessary. This may seem simple if the object is simply copied. But if you have to copy an object with a structure consisting of many arrays or hashes, you will have problems.

Objects and References

To understand what’s going on, let’s look at some simple examples. First, the assignment used in Ruby.

Here the assignment is taking the value of a and assigning it to b using the assignment. Any changes to a will not be related to b . But let’s go to a more complicated example?

Before running the above commands, try to guess what the output is and why. Unlike the previous example, when a changes, then b also changes, but what is the reason? Because arrays in Ruby are not of type POD. The assignment does not copy the value, but simply copies the reference to the original array that b points to in memory. Now a and b are pointing to the same array object, any changes to each variable will be visible to the other variable.

Now, you know why copying non-trivial objects with references to other objects can be difficult. If you simply copy an object, you are copying a reference from that object to the deeper object, so that copy is called “shllow copy”.

dup and clone

Ruby provides two methods for copying. Object # dup will create a “shallow copy” of the object. To do this, the dup method will call the initialize__copy method of that class. In some classes like Array, it will initialize a new array with the same number of elements as the original array. However it is not a deep copy. See the following example:

What is going on inside? The Array method # initialize_copy will make a copy of an array, but that copy is shallow copy. If you have any type of non-POD in your array, use dup to only partially copy. It only deep copies the first array (parent array), any deeper arrays (inside), hash or other objects will only be shallow copy.

There is another method called clone , which does the same thing as dup method with an important difference: It is expected that objects that will override this method with another method can perform a deep copy.

What does this mean in practice? Each class you can define a clone method to create a deep copy object of that class. That means you have to write the clone method for each class of the objects you want to copy.

Marshalling

Marshalling an object is a way to say serializing an object. In other words, turning an object into a stream of characters can be written to the file, then unmarshal or unserialize to retrieve the same object. This is applied to deep copy any object.

Share the news now

Source : Viblo