Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does String::sub!() change the original of a cloned object in Ruby?

I have a struct in my Ruby code that looks somewhat like this

Parameter = Struct.new(:name, :id, :default_value, :minimum, :maximum)

later, I create an instance of this struct using

freq = Parameter.new('frequency', 15, 1000.0, 20.0, 20000.0)

At some point, I need an exact duplicate of this struct, so I call

newFreq = freq.clone

Then, I change newFreq's name

newFreq.name.sub!('f', 'newF')

Which, miraculously, changes freq.name, too!

A simple assignment like newFreq.name = 'newFrequency' does not change freq.

Is this the way this is supposed to work?

Edit: Is it a good idea to use a class instead of a struct and overload clone to make a deep copy?

like image 997
bastibe Avatar asked Nov 17 '10 15:11

bastibe


1 Answers

newFreq is a shallow copy of freq. That means that each of the references stored inside of newFreq points to the object as the ones stored in freq. You can change where the references point independantly (newFreq.name = newFreq.name.sub 'f','newF'), but if you call a method that mutates the object, both newFreq and freq will be affected.

See also http://en.wikipedia.org/wiki/Object_copy

like image 120
Ken Bloom Avatar answered Nov 03 '22 04:11

Ken Bloom