2012-08-01 17 views
12

What's the difference between Ruby's dup and clone methods? opisuje różnicę w zachowaniu dup i clone. Ale kiedy należy użyć dup, a kiedy należy użyć clone?Kiedy używać dup i kiedy używać klonu w Ruby?

Przykłady z rzeczywistych projektów, które omawiają, dlaczego użyli dup, a nie klon, lub odwrotnie, byłyby idealne dla tego pytania.

W innym przypadku pomocne byłoby wyjaśnienie, dlaczego istnieją dwie różne metody. Może to odnosić się do wypowiedzi twórców Rubiego lub sprawdzenia metod takich jak dup i clone w językach, które wpłynęły na Ruby.

+0

Możliwy duplikat [Jaka jest różnica między dupą Rubiego a metodami klonowania?] (Http://stackoverflow.com/questions/10183370/whats-the-difference-between-rubys-dup-and-clone-methods) – OlehZiniak

Odpowiedz

7

prawdą jest, że clone kopiuje stan obiektu frozen, natomiast dup nie:

o = Object.new 
o.freeze 

o.clone.frozen? 
#=> true 

o.dup.frozen? 
#=> false 

clone będzie również kopiować metody singleton obiektu, gdy dup nie:

o = Object.new 
def o.foo 
    42 
end 

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

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

Co prowadzi mnie do założenia, że ​​clone jest czasami rozumiane jako zapewniające "głębszą" kopię niż dup. Oto kilka cytatów o temacie:

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

padli ofiarą oszustwa obiekty nie mają ID przypisane i są traktowane jako nowe rekordy. Uwaga: , że jest to "płytka" kopia, ponieważ kopiuje tylko atrybuty obiektu , a nie jej powiązania. Zakres "głębokiej" kopii jest konkretny i dlatego jest pozostawiony aplikacji, aby zaimplementować zgodnie z jej potrzebą, zgodnie z .

An article about deep copies in Ruby:

Jest jeszcze inna metoda Warto wspomnieć, clone. Metoda clone robi to samo co dup z jednym ważnym rozróżnieniem: oczekuje się, że obiekty zastąpią tę metodę tą, która może wykonywać głębokie kopie.

But then again, theres deep_dup in Rails 4:

Zwraca głęboką kopię obiektu jeśli to duplicable. Jeśli nie można go powielić, zwraca self.

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

clone - Identyczna jak metoda clone Ruby. To jest "płytka" kopia. Ostrzegaj, że twoje atrybuty nie są kopiowane. [...] Jeśli potrzebujesz kopii atrybutu atrybutów, użyj metody #dup.

Co oznacza, że ​​tutaj słowo dup jest używane do ponownego oznaczenia głębokiego klonu. O ile widzę, wydaje się, że nie ma konsensusu w społeczności, z wyjątkiem tego, że powinieneś używać clone i dup w przypadku, gdy potrzebujesz określonego efektu ubocznego jednego z nich.

Wreszcie, widzę dup znacznie częściej w kodzie Ruby niż clone. Nigdy dotąd nie używałem clone i nie będę tego robić, dopóki nie będę tego wyraźnie potrzebował.

+0

Na razie wygląda na to, że musisz użyć 'dup', chyba że masz powody do używania' clone' ('dup' wydaje się być prostszy). Ale może to dlatego, że teraz zajmuję się duplikowaniem hasza. Więc nie dbam o stan zamrożenia i klasę singleton. –

4

Zarówno DUP & CLONE można użyć do utworzenia płytkiej kopii obiektu. Obie kopie zmienne instancji obiektu. Ale musimy być selektywni w ich użyciu.

Kilka różnic pomiędzy są

1) kopii klonów zarówno zamrażane i splamionych stan obiektu, gdzie jako tylko DUP kopie splamionych stan obiektu.

2) Za pomocą CLONE można kopiować dowolne metody pojedynczego obiektu, ale DUP tego nie obsługuje.

Klon CLONE służy do duplikowania obiektu, w tym jego stanu wewnętrznego. DUP zazwyczaj używa klasy obiektu potomnego do utworzenia nowej instancji.

Miałem trochę gorzkiego doświadczenia podczas używania DUP do duplikowania wiersza ActiveRecord, co skończyło się utratą oryginału, tak samo działało z CLONE.

Jak owinięte się w zamieszaniu, znalazłem to jasne w Article of Open Source is Wide Open

+0

"Istnieją trzy sposoby kopiowania w Ruby: #dup, #klone i '='." - Jak '=' kopiuje? –

+0

Nie wchodzę głębiej w to, w jaki sposób "=" kopiuję, ale ona również tworzy płytką kopię. Oto [dobry przykład] (http://thingsaaronmade.com/blog/ruby-shallow-copy-surprise.html) na początek, ale w skrócie operator przypisania nie tworzy kopii wartości, po prostu kopiuje odniesienie do obiektu –

+0

Po prostu Uwaga: 'Marshal :: load (Marshal.dump (foo))' działa, ale może powodować problemy z modelami baz danych. – sandstrom