2012-08-01 18 views
12

What's the difference between Ruby's dup and clone methods? describe la diferencia en el comportamiento de dup y clone. ¿Pero cuándo debo usar dup, y cuando debería usar clone en su lugar?Cuándo usar dup, y cuándo usar clon en Ruby?

Ejemplos de proyectos reales que discuten por qué usaron dup en lugar de clonar, o viceversa, serían ideales para esta pregunta.

Alternativamente, una explicación de por qué existen los dos métodos diferentes sería útil. Esto podría referirse a declaraciones de los creadores de Ruby, o un examen de métodos como dup y clone en idiomas que influyeron en Ruby.

+0

Posible duplicado de [¿Cuál es la diferencia entre los métodos de Duplicación y clonación de Ruby?] (Http://stackoverflow.com/questions/10183370/whats-the-difference-between-rubys-dup-and-clone-methods) – OlehZiniak

Respuesta

7

Es cierto que clone copia el estado de un objeto frozen, mientras dup no:

o = Object.new 
o.freeze 

o.clone.frozen? 
#=> true 

o.dup.frozen? 
#=> false 

clone también copiará los métodos singleton del objeto, mientras que dup no:

o = Object.new 
def o.foo 
    42 
end 

o.clone.respond_to?(:foo) 
#=> true 

o.dup.respond_to?(:foo) 
#=> false 

que me lleva a la suposición de que clone se entiende a veces como para proporcionar una copia "profundo" que dup. Aquí hay algunas citas sobre el tema:

Comment on ActiveRecord::Base#initialize_dup from Rails 3:

objetos engañados han asignado ningún id y se tratan como nuevos registros. Tenga en cuenta que esta es una copia "poco profunda" ya que copia los atributos del objeto solamente, no sus asociaciones. La extensión de una copia "profunda" es específica de la aplicación y, por lo tanto, se deja a la aplicación implementar de acuerdo con a su necesidad.

An article about deep copies in Ruby:

Hay otro método vale la pena mencionar, clone. El método clone hace lo mismo que dup con una distinción importante: se espera que los objetos anulen este método con uno que pueda hacer copias en profundidad.

But then again, theres deep_dup in Rails 4:

Devuelve una copia profunda de objeto si es duplicable. Si no es duplicable, devuelve self.

and also ActiveRecord::Core#dup and #clone in Rails 4:

clone - Idéntico al método clone de Ruby. Esta es una copia "superficial". Tenga en cuenta que sus atributos no se copian. [...] Si necesita una copia de sus atributos hash, use el método #dup.

Lo que significa que aquí, la palabra dup se utiliza para referirse a un clon de profundidad de nuevo. Por lo que puedo ver, parece que no hay consenso en la comunidad, excepto que debe usar clone y dup en el caso cuando necesite un efecto secundario específico de cualquiera de los dos.

Finalmente, veo dup con mucha más frecuencia en el código de Ruby que clone. Nunca he usado clone hasta ahora, y no lo haré hasta que explícitamente lo necesite.

+0

Por ahora me parece que tienes que usar 'dup', a menos que tengas razones para usar' clone' ('dup' parece ser más simple). Pero tal vez sea porque ahora me preocupa duplicar un hash. Así que no me importa el estado congelado y una clase singleton. –

4

Tanto DUP & CLONE se puede utilizar para crear copia superficial de un objeto. Ambos copian las variables de instancia de obj. Pero debemos ser selectivos en su uso.

pocos diferencia entre estos son

1) copias CLONE tanto congelado y estatales TAINTED de un objeto, donde como DUP sólo copias corrompido estado de un objeto.

2) Con CLONE puede copiar cualquier método singleton de un objeto pero DUP no lo admite.

CLONE se utiliza para duplicar un objeto, incluido su estado interno, DUP normalmente utiliza la clase del objeto descendiente para crear la nueva instancia.

Tuve una experiencia amarga al usar DUP para duplicar una fila ActiveRecord, esto terminó en la pérdida de la original, lo mismo funcionó bien con CLONE.

Como Me envolví en la confusión, me pareció claro en una Article of Open Source is Wide Open

+0

"Hay tres maneras de copiar en Ruby: #dup, #clone y '='". - ¿Cómo '' '' copia? –

+0

No profundizo en cómo '=' copiar, pero también hace una copia superficial. Aquí hay un [buen ejemplo] (http://thingsaaronmade.com/blog/ruby-shallow-copy-surprise.html) para empezar, pero en resumen, el operador de asignación no hace una copia del valor, simplemente copia la referencia al objeto –

+0

Solo una nota: 'Marshal :: load (Marshal.dump (foo))' funciona, pero puede causar problemas con los modelos de la base de datos. – sandstrom

Cuestiones relacionadas