Last Updated: May 03, 2023
·
70.71K
· mattetti

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.

5 Responses
Add your response

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 ·

@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 ·

Thanks :)

over 1 year ago ·

There's a lot of software out there for your PC:

over 1 year ago ·

Thanks for this

over 1 year ago ·