2012-08-01 20 views
12

What's the difference between Ruby's dup and clone methods? descrive la differenza nel comportamento di dup e clone. Ma quando dovrei usare dup e quando invece dovrei usare clone?Quando usare dup e quando usare clone in Ruby?

Esempi di progetti reali che discutono sul motivo per cui hanno usato dup anziché cloni, o viceversa, sarebbero ideali per questa domanda.

In alternativa, sarebbe utile una spiegazione del motivo per cui esistono due metodi diversi. Questo potrebbe riferirsi a dichiarazioni dei creatori di Ruby o ad un esame di metodi come dup e clone in lingue che hanno influenzato Ruby.

+0

Possibile duplicato di [Qual è la differenza tra i metodi dup e clone di Ruby?] (Http://stackoverflow.com/questions/10183370/whats-the-difference-between-rubys-dup-and-clone-methods) – OlehZiniak

risposta

7

E 'vero che clone copia il frozen stato di un oggetto, mentre dup non lo fa:

o = Object.new 
o.freeze 

o.clone.frozen? 
#=> true 

o.dup.frozen? 
#=> false 

clone copierà anche i metodi singleton dell'oggetto mentre dup non:

o = Object.new 
def o.foo 
    42 
end 

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

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

Il che mi porta a supporre che il numero clone venga talvolta interpretato come una copia "più profonda" rispetto a dup. Ecco alcune citazioni sul tema:

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

oggetti ingannati hanno alcun ID assegnato e vengono trattati come nuovi record. Nota: questa è una copia "superficiale" poiché copia solo gli attributi dell'oggetto , non le sue associazioni. L'estensione di una copia "profonda" è l'applicazione specifica ed è quindi lasciata all'applicazione da implementare in base a in base alle proprie necessità.

An article about deep copies in Ruby:

c'è un altro metodo degno di nota, clone. Il metodo clone fa la stessa cosa di dup con un'importante distinzione: è previsto che gli oggetti sovrascrivano questo metodo con uno che può eseguire copie profonde.

But then again, theres deep_dup in Rails 4:

Restituisce una copia completa di oggetto se è duplicabile. Se non è duplicabile, restituisce self.

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

clone - Identico al metodo clone di Ruby. Questa è una copia "superficiale". Tieni presente che i tuoi attributi non vengono copiati. [...] Se è necessaria una copia dell'hash hash, utilizzare il metodo #dup.

Ciò significa che in questo caso la parola dup viene utilizzata per riferirsi nuovamente a un clone profondo. Per quanto posso vedere, sembra non esserci consenso nella comunità, tranne che si dovrebbe usare clone e dup nel caso in cui si abbia bisogno di uno specifico effetto collaterale di uno dei due.

Infine, vedo dup molto più spesso in codice Ruby di clone. Non ho mai usato lo clone finora, e lo farò solo quando ne avrò bisogno esplicitamente.

+0

Per ora mi sembra che tu debba usare 'dup', a meno che tu non abbia i motivi per usare' clone' ('dup' sembra essere più semplice). Ma forse è perché ora mi occupo di duplicare un hash. Quindi non mi importa dello stato congelato e di una classe singleton. –

4

Entrambi DUP & CLONE può essere utilizzato per creare una copia superficiale di un oggetto. Entrambe copia le variabili di istanza di obj. Ma dobbiamo essere selettivi nel loro utilizzo.

Pochi differenza tra questi sono

1) CLONE copie sia stato congelato e viziata di un oggetto, in cui come DUP solo copie contaminato stato di un oggetto.

2) Con CLONE è possibile copiare qualsiasi metodo singleton di un oggetto ma DUP non supporta questo.

CLONE è utilizzato per duplicare un oggetto, incluso il suo stato interno, in genere DUP utilizza la classe dell'oggetto discendente per creare la nuova istanza.

Ho avuto qualche esperienza amara durante l'utilizzo di DUP per la duplicazione di una riga di ActiveRecord, questo ha finito per perdere quello originale, lo stesso funzionava bene con CLONE.

Come io stesso ho avvolto nella confusione, ho trovato in chiaro in un Article of Open Source is Wide Open

+0

"Ci sono tre modi per copiare in Ruby: #dup, #clone e '='." - Come '=' copia? –

+0

Non approfondisco il modo in cui '=' copia, ma anche una copia superficiale. Ecco un [buon esempio] (http://thingsaaronmade.com/blog/ruby-shallow-copy-surprise.html) per l'avvio, ma in sintesi l'operatore di assegnazione non fa una copia del valore, semplicemente copia il riferimento all'oggetto –

+0

Solo una nota: 'Marshal :: load (Marshal.dump (foo))' funziona, ma potrebbe causare problemi con i modelli di database. – sandstrom