Misunderstanding the Passing of references


#1

I’m to to ruby…

Currently, I’m stuck in a situation where I’m changing values I’m not
intending to and I don’t know how to correct it.

I have… A class “Model” and a class “DataObject”. The “Data Object”
class has a method which takes in a “Model” and returns a new “Model”.
The problem is, my “generate_new_model” method is altering the input
“Model” object.

The below show basically what I’ve done to create the objects. Somehow
when I define a new “Model” for output and set it’s values to the source
model’s values, when I change the outputModel values it alters the
source model.

What am I doing wrong?

@myModel = Model.new
@myData = DataObject.new

newModel = @myData.generate_new_model(@myModel)

def generate_new_model(modelSource)
outputModel = Model.new
outputModel = modelSource

outputModel.values = "new values"

outputModel

end


#2

@myModel = Model.new
@myData = DataObject.new

newModel = @myData.generate_new_model(@myModel)

def generate_new_model(modelSource)
outputModel = Model.new

So far, so good. At the minute, outputModel references a brand new
Model.

outputModel = modelSource

Now, however, it references the same model as modelSource. Oops.

outputModel.values = "new values"

And here you’ve changed the values of the Model referenced by
outputModel and modelSource.

outputModel

end

Am I right in guessing that you’re trying to put a copy of
modelSource into outputModel? If so, you might want to take a look
at this:

http://www.rubygarden.org/ruby?Make_A_Deep_Copy_Of_An_Object

Depending on the structure of the Model class, it might be better to
give it its own copy method.

matthew smillie.


#3

Am I right in guessing that you’re trying to put a copy of
modelSource into outputModel?

That’s exactly the case. In reading the link you suggest it seems I
would have to use a seperate data dumping operation. This seems a
little strange to me. Shouldn’t there be a more simple way to create a
copy of an object?


#4

Just to provide some direct information for anyone who might find this
and need the help…

The below does indeed solve the problem…

class Model
def deep_clone
Marshal::load(Marshal.dump(self))
end
end

a = Model.new
b = Model.deep_clone

Thank you very much for your help.


#5

On Jan 30, 2006, at 6:43, Todd S. wrote:

In reading the link you suggest it seems I
would have to use a seperate data dumping operation. This seems a
little strange to me. Shouldn’t there be a more simple way to
create a
copy of an object?

There is and there isn’t: Object#dup and #clone both make shallow
copies:
http://ruby-doc.org/core/classes/Object.html#M001067

There’s no built-in method to create deep copies of any object,
though, and the serialise/unserialise thing just hacks around that in
the quickest way (as in, quickest to write).

If it were me, unless the Model class was extraordinarily
complicated, I’d probably just write my own copy method.

matthew smillie.


#6

On Jan 30, 2006, at 1:50 AM, Todd S. wrote:

a = Model.new
b = Model.deep_clone

Thank you very much for your help.


Posted via http://www.ruby-forum.com/.

This isn’t perfect but:
class Object
def deeper_copy
copy = self.dup
self.instance_variables.each do |ivar|
copy.instance_variable_set(ivar,
self.instance_variable_get(ivar).dup)
end
copy
end
end

Note that this is specifically designed to work for regular style
classes (ie ones that store everything in instance variables) and
for Strings, Arrays and Structs its no better than (but no worse
than) #dup. Hence “deeper_copy” instead of “deep_copy”


#7

Matthew S. wrote:

http://ruby-doc.org/core/classes/Object.html#M001067

There’s no built-in method to create deep copies of any object,
though, and the serialise/unserialise thing just hacks around that in
the quickest way (as in, quickest to write).

If it were me, unless the Model class was extraordinarily
complicated, I’d probably just write my own copy method.

You can as well override or reimplement the #dup method.

robert