On 10/14/09, Robert Klemme <shortcutter / googlemail.com> wrote:
> 2009/10/14 Rajinder Yadav <devguy.ca / gmail.com>:
>> I am trying to figure out how to perform a deep clone
>>
>>
>> class A
>>   attr_accessor :name
>> end
>>
>> a1 = A.new
>> a1.name = "yoyoma"
>> a2 = a1.dup
>> a1.name.chop!
>> puts a2.name
>>
>>
>> I found the following way to write a deep clone method
>>
>> class A
>>  attr_accessor :name
>>  def dup
>>     Marshal::load(Marshal.dump(self))
>>  end
>> end
>>
>> If I wanted to write my own specialize deep_cloner, how would I do this.
>> If
>> I try the obvious way to do it,
>>
>> def dup
>>   @name = self.name.dup
>> end
>
> No, this is by far not the obvious way since you would at least have
> to make sure there is a copy of self and this is returned from dup.  I
> would rather do
>
> def dup
>   copy = super
>   copy.name = @name.dup
>   copy
> end
>
> or even
>
> def dup
>   self.class.new(@name.dup)
> end
>
> Although that approach is fragile depending on the code in #initialize.

The documentation of Object#dup seems to suggest that subclasses
should not override dup, preferring to override clone instead. I'm not
sure why this should be or why overriding dup would be bad. But
anyway, I would suggest this:

def deep_clone
  copy=clone
  copy.name=@name.clone
  copy
end

just so you can keep the existing semantics of clone as a shallow copy.

I'm really not sure why there are 2 methods to create shallow copies
in ruby and what all the differences are supposed to be. Other than
not overriding dup(?), the only other difference between them that I
can discover is that clone copies the metaclass of the object, whereas
dup reverts the copy's metaclass to being just its class. I've been
wondering about the difference between the 2 recently; I hope someone
out there can provide some enlightenment on why there are 2 and what
the differences are.