Ruby: the differences between dup & clone
Have you ever wondered what the differences are between #dup and #clone in Ruby?
They both create a shallow copy of an object (meaning that they don't copy the objects that might be referenced within the copied object). However, #clone does two things that #dup doesn't:
- copy the singleton class of the copied object
- maintain the frozen status of the copied object
Examples of the singleton methods not being copied.
dup:
a = Object.new
def a.foo; :foo end
p a.foo
# => :foo
b = a.dup
p b.foo
# => undefined method `foo' for #<Object:0x007f8bc395ff00> (NoMethodError)
vs clone:
a = Object.new
def a.foo; :foo end
p a.foo
# => :foo
b = a.clone
p b.foo
# => :foo
Frozen state:
a = Object.new
a.freeze
p a.frozen?
# => true
b = a.dup
p b.frozen?
# => false
c = a.clone
p c.frozen?
# => true
Looking at the Rubinius source code makes the difference extremely obvious.
Because of the extra steps, clone is a bit slower than dup but that's probably not what will make your app too slow.
Just a quick note about shallow copies (true for clone and dupe). Notice how the array referenced by the bar attribute doesn't get copied but shared between the original and the copied instances:
class Foo
attr_accessor :bar
def initialize
self.bar = [1,2,3]
end
end
a = Foo.new
b = a.clone
p a.bar
# => [1, 2, 3]
p b.bar
# => [1, 2, 3]
a.bar.clear # clearing the array #bar points to
p a.bar
# => []
p b.bar
# => []
Both objects, a and b share the same reference to the array instance created when a is initiated. There are a few ways to do a deep copy of an object, but that's a different matter.
For more tips, articles and presentations see my personal site.
Written by Matt Aimonetti
Related protips
5 Responses
In Dave and Chad's Ruby class they have a mnemonic that's used: Clone copies, dup doesn't. Although incomplete per your definition above, it's a quick way to remember.
@annavester freeze will indeed lock the object, making it immutable. This means that it cannot be changed any more. You can't unfreeze an object once it's frozen, because that would mean modifying the object from an immutable to a mutable state. Accordingly, there's no unfreeze method. More information can be found here: http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html
Thanks :)
There's a lot of software out there for your PC:
Thanks for this