1zflyg
Last Updated: September 21, 2017
·
42.33K
· mattetti
Matt aimonetti portait 2011 sq400

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.

Say Thanks
Respond

4 Responses
Add your response

1240
2b7e2ffef45c93c13a4a29fa06fcff69

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.

over 1 year ago ·
2519
A7f2c4b96b0e29655e5bf30e77c47cf0

I am relatively new to ruby, still learning. Does frozen mean that it's in sort of a locked state (meaning nothing can be added/changed). Can it be un-frozen? Thanks!

over 1 year ago ·
9904
Aec924d6fd4f693e4a93c1f463c5023a

@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

over 1 year ago ·
28937

Thanks :)

4 months ago ·