Which method to define on a Ruby class to provide dup / clone for its instances?

clone, dup, ruby

Solution

From my experience, overloading #initialize_copy works just fine (never heard about initialize_dup and initialize_clone).

The original initialize_copy (which initializes every instance variable with the values from the original object) is available through super, so I usually do:

class MyClass
  def initialize_copy(orig)
    super
    # Do custom initialization for self
  end
end

Problem

I have a `Pointer` class with a single attribute `:contents`, that points to an object of class `MyObject`. ``` class MyObject def hello; "hello" end end class Pointer attr_reader :contents def initialize( cont ); @contents = cont end # perhaps define some more state end ``` I want my `Pointer` to be able to make copies of itself. I know that `#dup` method is defined by default, while `#clone` method is expected to be overriden to be able to make deep copies. But here, the copies don't have to be too deep. So, the first dilemma that I have is, should I override `#dup` method, because I don't really want to copy the additional state of my `Pointer`, just make a new one pointing to the same `MyObject` instance? Or should I refrain from overridine `#dup`, because I am not "supposed to" and override `#clone` with a method making shallow copies? I would welcome comments on the above, but let's say that I will choose to override `#dup`. I could do just this: ``` class Pointer def dup; self.class.new( contents ) end end ``` But online, I read something like "the dup method will call the initialize copy method". Also, this guy writes about `#initialize_clone`, `#initialize_dup` and `#initialize_copy` in Ruby. That leaves me wondering, is the best practice perhaps like this? ``` class Pointer def initialize_copy # do I don't know what end end ``` Or like this? ``` class Pointer def initialize_dup # do I don't know what end end ``` Or should I just forget about online rants written to confuse beginners and go for overriding `#dup` without concerns? Also, I do understand that I can just call `#dup` without defining any custom `#dup`, but what if I want to define `#dup` with different behavior? Also, the same question apply to `#clone` - should I try to define `#initialize_clone` or just `#clone`?

Original source