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 str str = "this is a test string" # accepts a string def modifyAnyString (strVar) # string is replaced with another string changing the value strVar.replace("this is a modified version of strVar") end # call the modify string with the str variable modifyAnyString(str) puts str # outputs: this is a modified version of strVar
In 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 object
end
puts 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_multi
dup_multi.freeze
frz_dup_multi = dup_multi.dup
# false original multiverse has not been frozen
puts multiverse.frozen?
# true The dup_multi was frozen before duplication
puts 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_multi
copy_multi.freeze
frz_copy_multi = copy_multi.dup
# false original multiverse has not been frozen
puts multiverse.frozen?
# false The copy_multi was frozen before duplication
puts 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! 🙇