Ruby: the difference between clone and dup

#clone does two things that #dup doesn’t:

Singleton Class

a = Object.new
def a.foo
  :foo
end

b = a.dup
p b.foo rescue 'NoMethodError'

c = a.clone
p c.foo

Frozen Status

a = Object.new
a.freeze
p a.frozen? # => true
b = a.dup
p b.frozen? # => false
c = a.clone
p c.frozen? # => true

Array attribute shared between original and copied instances, #clone and #dup are the same.

class Foo
  attr_accessor :bar
  def initialize
    self.bar = [1,2,3]
  end
end

a = Foo.new
b = a.clone
c = a.dup
p a.bar # => [1,2,3]
p a.bar.clear # => []
p b.bar # => []
p c.bar # => []

Deep Copy Marshal

a = [1,2,3]
b = Marshal.load(Marshal.dump(a))
b << 4
p a # => [1,2,3]
p b # => [1,2,3,4]

class Document  
    attr_accessor :title, :text  
    attr_reader :timestamp  

    def initialize(title, text)  
        @title, @text = title, text  
        @timestamp = Time.now  
    end  
end

above ruby 2.3.1, dup, clone are not share the same memory reference,they are new object

a = [1,2,3]
b = a.dup
c = a.clone

b << 4
c.clear

p a # => [1,2,3]

initialize_copy

class Document  
  attr_accessor :title, :text  
  attr_reader :timestamp  

  def initialize(title, text)  
    @title, @text = title, text  
    @timestamp = Time.now  
  end  
end

doc = Document.new("Ruby", "Array")
sleep 2
doc_copy = doc.clone

doc.timestamp == doc_copy.timestamp # => ture
class Document  
  attr_accessor :title, :text  
  attr_reader :timestamp  

  def initialize(title, text)  
    @title, @text = title, text  
    @timestamp = Time.now  
  end

  def initialize_copy(new_object)
    p other
    @timestamp = Time.now
  end
end

doc = Document.new("Ruby", "Array")
sleep 2
doc_copy = doc.clone

doc.timestamp == doc_copy.timestamp # => false

Reference:

Ruby: the differences between dup & clone ruby复制对象的方法(dup 和 clone)