Suppose I have an class that needs to implement its own dup/clone
methods. What is the correct way to write these methods?
One way is to create protected accessors:
class Foo
def initialize(foo, bar)
@foo = foo
@bar = bar
end
def dup
copy = super
copy.foo = @foo.dup
copy.bar = @bar.dup
end
protected
attr_accessor :foo
attr_accessor :bar
end
Another way is to use instance_eval:
class Foo
def dup
copy = super
foo = @foo.dup
bar = @bar.dup
copy.instance_eval do
@foo = foo
@bar = bar
end
end
end
Questions:
1. How else might dup/clone be implemented? (the deep-copy trick using
marshaling is one way, but the goal here is to write a one-level-deep
dup/clone).
2. What is the right way to set the new instance variables in the copy?
3. Should dup be implemented in terms of clone or should clone be
implented in terms of dup (or should they both be implemented
independently or in terms of another function)?
4. When making the copy, is super the right way to make the copy, or
should allocate be used? (allocate doesn't work on 1.6.x, which I
still use heavily, though if it's the right solution, then it's the
right solution).
5. Certain types cannot be dup'd (e.g. NilClass in all versions of Ruby
or Fixnum in 1.8 and later), so the above code will break if I write:
Foo.new(10, 42).dup
Is it possible (or is it even wise) to write a dup or clone function
that works with both value types and container types?
Paul