Question

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?

Was it helpful?

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top