Creating multiple copies of objects in Ruby
September 07, 2023
Since everything is an object in Ruby having a functionality that can duplicate objects is not a bad idea.
Ruby ships with two methods for making copies of an object: the dup
method and the clone
method.
In Ruby, all variables hold a reference to an object. In a case where a section of a code modifies an object that is not meant to be modified, it is ideal to make a copy of that object to be used in that section of the code, protecting the integrity of the copied object.
# initial value of strstr = "this is a test string"# accepts a stringdef modifyAnyString (strVar)# string is replaced with another string changing the valuestrVar.replace("this is a modified version of strVar")end# call the modify string with the str variablemodifyAnyString(str)puts str # outputs: this is a modified version of strVarIn some languages like C# and Java, this is called passing by value or dereferencing.
The dup
method
Take this multiverse
object initialized below:
multiverse = Object.new
We can pass multiverse
to any method that has a write operation, this would affect the object.
def getObjectID (obj)obj.object_id # returns the object ID of the passed objectendputs getObjectID(multiverse) == multiverse.object_id # true
To avoid sending in the exact object by reference use the Object.dup
method to create a copy of an object.
puts getObjectID(multiverse.dup) == multiverse.object_id # false
Now, it is safer to pass the duplicated variable to a method. This would protect modifying multiverse
objects in the getObjectID
method if the method is not meant to do any write operation on the object.
Note: If an object is frozen, the returned object will remain frozen, even after it has been duplicated.
dup_multi = multiverse.dup# freeze the dup_multidup_multi.freezefrz_dup_multi = dup_multi.dup# false original multiverse has not been frozenputs multiverse.frozen?# true The dup_multi was frozen before duplicationputs frz_dup_multi.frozen?
The copy
method
Copying an object is almost the same as duplicating an object, the only difference is that, when copying, if the object is frozen, the copied object becomes unfrozen.
copy_multi = multiverse.dup# freeze the dup_multicopy_multi.freezefrz_copy_multi = copy_multi.dup# false original multiverse has not been frozenputs multiverse.frozen?# false The copy_multi was frozen before duplicationputs frz_copy_multi.frozen?
This can be useful to create a copy of the same object that is not restricted either by the function caller or by developers who want to ensure that a method consistently works with unfrozen objects.
Salut! 🙇
Edit on githubTweet