Dokumenty Rubydup
mówią:
Ogólnie rzecz biorąc,
clone
idup
może mieć różną semantykę w klasach potomnych. Chociażclone
służy do duplikowania obiektu, w tym jego stanu wewnętrznego,dup
zwykle używa klasy obiektu potomnego do utworzenia nowej instancji.
Ale kiedy wykonuję jakiś test, okazało się, że są one takie same:
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7
Jakie są zatem różnice między tymi dwiema metodami?
dup
i coclone
robi, ale dlaczego używasz jednego zamiast drugiego.Odpowiedzi:
Podklasy mogą zastąpić te metody, aby zapewnić inną semantykę. W
Object
sobie, istnieją dwie zasadnicze różnice.Najpierw
clone
kopiuje klasę singleton, adup
nie robi tego.Po drugie,
clone
zachowuje stan zamrożenia, podczas gdydup
nie.Realizacja Rubinius dla tych metod jest często moje źródło odpowiedzi na te pytania, ponieważ jest to dość oczywiste, a realizacja dość zgodny Ruby.
źródło
o = Object.new; class << o; A=5; end; puts ( class << o.clone; A; end ); puts ( class << o.dup; A; end )
.extend
edytowane na oryginalnym obiekcie.Object.new.extend(Enumerable).dup.is_a?(Enumerable)
Zwraca więc wartość false.W przypadku ActiveRecord istnieje również znacząca różnica:
dup
tworzy nowy obiekt bez ustawionego identyfikatora, dzięki czemu można zapisać nowy obiekt w bazie danych, naciskając.save
clone
tworzy nowy obiekt o tym samym identyfikatorze, więc wszystkie zmiany dokonane w tym nowym obiekcie zastąpią oryginalny rekord w przypadku uderzenia.save
źródło
dup
iclone
metody na mójActiveRecord
obiekt, otrzymuję odwrotne wyniki tego, o czym wspomniałeś w odpowiedzi. co oznacza, że kiedy używamdup
, tworzy nowy obiekt zid
ustawionym, a podczas używaniaclone
tworzy obiekt bezid
ustawiania. czy możesz zajrzeć do niego jeszcze raz i wyjaśnić? . Thnxclone
wprowadzenie nowego rekordu, który nigdy nie został zapisany, powinno być całkiem bezpieczne? Czy mogę w ten sposób zbudować „obiekt szablonu” i sklonować go, aby zapisać określone wystąpienia?Jedną różnicą są zamrożone przedmioty.
clone
Zamrożonej przedmiotu jest również zamrożone (podczas gdydup
zamrożonej obiektu nie).Kolejna różnica dotyczy metod singletonowych. Ta sama historia tutaj,
dup
nie kopiuje ich, aleclone
robi.źródło
Oba są prawie identyczne, ale klon robi coś więcej niż dup. W klonie kopiowany jest również stan zamrożenia obiektu. W dupleksie zawsze będzie rozmrażany.
źródło
Nowsze doc zawiera dobry przykład:
źródło
Klonu można użyć do programowania opartego na prototypach w języku Ruby. Klasa Object Ruby definiuje zarówno metodę klonowania, jak i metodę dup. Zarówno klon, jak i dup tworzą płytką kopię obiektu, który kopiuje; to znaczy zmienne instancji obiektu są kopiowane, ale nie obiekty, do których się odnoszą. Pokażę przykład:
Zauważ, że w powyższym przykładzie pomarańczowy klon kopiuje stan (tj. Zmienne instancji) obiektu Apple, ale w przypadku gdy obiekt Apple odwołuje się do innych obiektów (takich jak kolor obiektu String), te odniesienia nie są kopiowane. Zamiast tego jabłko i pomarańcza odnoszą się do tego samego obiektu! W naszym przykładzie referencją jest obiekt łańcuchowy „czerwony”. Gdy pomarańczowy używa metody dołączania <<, aby zmodyfikować istniejący obiekt String, zmienia obiekt string na „czerwony pomarańczowy”. To w efekcie zmienia także apple.color, ponieważ oba wskazują na ten sam obiekt String.
Na marginesie, operator przypisania = = przypisze nowy obiekt i tym samym zniszczy odniesienie. Oto demonstracja:
W powyższym przykładzie, kiedy przypisaliśmy nowy nowy obiekt do metody instancji kolorów pomarańczowego klonu, nie odnosi się on już do tego samego obiektu co jabłko. Dlatego możemy teraz zmodyfikować metodę koloru pomarańczowego bez wpływu na metodę koloru jabłka, ale jeśli sklonujemy inny obiekt z jabłka, nowy obiekt będzie odwoływał się do tych samych obiektów w skopiowanych zmiennych instancji jak jabłko.
dup wytworzy również płytką kopię obiektu, który kopiuje, a jeśli miałbyś zrobić taką samą demonstrację, jak pokazano powyżej, zobaczysz, że działa dokładnie w ten sam sposób. Istnieją jednak dwie główne różnice między klonowaniem a duplikatem. Po pierwsze, jak wspomniano inni, klon kopiuje stan zamrożenia, a duplikat nie. Co to znaczy? Termin „zamrożony” w Rubim jest ezoterycznym terminem niezmiennym, który sam w sobie jest nomenklaturą w informatyce, co oznacza, że czegoś nie można zmienić. Dlatego zamrożonego obiektu w Rubim nie można w żaden sposób modyfikować; w rzeczywistości jest niezmienny. Jeśli spróbujesz zmodyfikować zamrożony obiekt, Ruby zgłosi wyjątek RuntimeError. Ponieważ klon kopiuje stan zamrożenia, próba zmodyfikowania sklonowanego obiektu spowoduje zgłoszenie wyjątku RuntimeError. I odwrotnie, ponieważ dup nie kopiuje stanu zamrożenia,
Po drugie i, co ciekawsze, klon kopiuje klasę singleton (a stąd i jej metody)! Jest to bardzo przydatne, jeśli chcesz podjąć się programowania opartego na prototypach w Rubim. Najpierw pokażmy, że rzeczywiście metody singletonowe są kopiowane z klonem, a następnie możemy zastosować je w przykładzie programowania opartego na prototypach w Ruby.
Jak widać klasa singleton instancji obiektu owocowego jest kopiowana do klonu. I tak sklonowany obiekt ma dostęp do metody singleton: seeded ?. Ale nie jest tak w przypadku dup:
Obecnie w programowaniu opartym na prototypach nie ma klas, które rozszerzają inne klasy, a następnie tworzą instancje klas, których metody pochodzą od klasy nadrzędnej, która służy jako plan. Zamiast tego masz obiekt podstawowy, a następnie tworzysz nowy obiekt z obiektu za pomocą jego metod i stanu skopiowano (oczywiście, ponieważ wykonujemy płytkie kopie za pośrednictwem klonowania, wszelkie obiekty, do których odwołują się zmienne instancji, będą udostępniane tak jak w JavaScript prototypy). Następnie możesz wypełnić lub zmienić stan obiektu, wypełniając szczegóły sklonowanych metod. W poniższym przykładzie mamy podstawowy obiekt owocowy. Wszystkie owoce mają nasiona, dlatego tworzymy metodę liczba nasion. Ale jabłka mają jedno ziarno, więc tworzymy klon i uzupełniamy szczegóły. Teraz, kiedy klonujemy jabłko, nie tylko klonujemy metody, ale także klonujemy państwo! Pamiętaj, że klon wykonuje płytką kopię stanu (zmienne instancji). Z tego powodu, gdy sklonujemy jabłko, aby uzyskać red_apple, red_apple automatycznie otrzyma 1 ziarno! Możesz myśleć o red_apple jako obiekcie, który dziedziczy po Apple, który z kolei dziedziczy po Fruit. Dlatego właśnie dokapitalizowałem Fruit and Apple. Zlikwidowaliśmy rozróżnienie między klasami a przedmiotami dzięki uprzejmości klonów.
Oczywiście możemy mieć metodę konstruktora w programowaniu opartym na protoype:
Ostatecznie, używając klonowania, możesz uzyskać coś podobnego do zachowania prototypowego JavaScript.
źródło