What's the difference between Ruby's dup and clone methods?
Subclasses may override these methods to provide different semantics. In Object
itself, there are two key differences.
First, clone
copies the singleton class, while dup
does not.
o = Object.new
def o.foo
42
end
o.dup.foo # raises NoMethodError
o.clone.foo # returns 42
Second, clone
preserves the frozen state, while dup
does not.
class Foo
attr_accessor :bar
end
o = Foo.new
o.freeze
o.dup.bar = 10 # succeeds
o.clone.bar = 10 # raises RuntimeError
The Rubinius implementation for these methods is often my source for answers to these questions, since it is quite clear, and a fairly compliant Ruby implementation.
When dealing with ActiveRecord there's a significant difference too:
dup
creates a new object without its id being set, so you can save a new object to the database by hitting .save
category2 = category.dup
#=> #<Category id: nil, name: "Favorites">
clone
creates a new object with the same id, so all the changes made to that new object will overwrite the original record if hitting .save
category2 = category.clone
#=> #<Category id: 1, name: "Favorites">
One difference is with frozen objects. The clone
of a frozen object is also frozen (whereas a dup
of a frozen object isn't).
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
x.freeze
y = x.dup
z = x.clone
y.x = 5 => 5
z.x = 5 => TypeError: can't modify frozen object
Another difference is with singleton methods. Same story here, dup
doesn't copy those, but clone
does.
def x.cool_method
puts "Goodbye Space!"
end
y = x.dup
z = x.clone
y.cool_method => NoMethodError: undefined method `cool_method'
z.cool_method => Goodbye Space!