Você já se perguntou quais são as diferenças entre #dup e #clone em Ruby?
Ambos criam uma cópia superficial de um objeto (o que significa que eles não copiam os objetos que podem ser referenciados no objeto copiado). No entanto, #clone faz duas coisas que #dup não faz:
- copie a classe singleton do objeto copiado
- manter o status congelado do objeto copiado
Exemplos de métodos singleton que não estão sendo copiados.
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
Estado congelado:
a = Object.new
a.freeze
p a.frozen?
# => true
b = a.dup
p b.frozen?
# => false
c = a.clone
p c.frozen?
# => true
Olhar para o código-fonte do Rubinius torna a diferença extremamente óbvia.
Por causa das etapas extras, clone é um pouco mais lento do que dup, mas provavelmente não é isso que tornará seu aplicativo muito lento.
Apenas uma nota rápida sobre cópias superficiais (verdadeiro para clone e dupe ). Observe como a matriz referenciada pelo atributo bar não é copiada, mas compartilhada entre as instâncias original e copiada:
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
# => []
Ambos os objectos, um e b compartilham a mesma referência ao exemplo matriz criada quando um é iniciada. Existem algumas maneiras de fazer uma cópia profunda de um objeto, mas isso é diferente.
Para mais dicas, artigos e apresentações, consulte meu site pessoal .