2012-08-14 12 views
9

Mam klasę Pointer z pojedynczym atrybutem :contents, która wskazuje obiekt klasy MyObject.Którą metodę należy zdefiniować w klasie Ruby, aby zapewnić dup/clone dla jej instancji?

class MyObject 
    def hello; "hello" end 
end 

class Pointer 
    attr_reader :contents 
    def initialize(cont); @contents = cont end 
    # perhaps define some more state 
end 

Chcę, aby mój Pointer mógł tworzyć własne kopie. Wiem, że metoda #dup jest zdefiniowana domyślnie, a metoda #clone ma zostać przesłonięta, aby móc wykonywać głębokie kopie. Ale tutaj kopie nie muszą być zbyt głębokie. Tak więc, pierwszym dylematem, który mam jest, powinienem zastąpić metodę #dup, ponieważ tak naprawdę nie chcę kopiować dodatkowego stanu mojego Pointer, wystarczy zrobić nowy wskazujący na tę samą instancję MyObject? Czy też powinienem powstrzymać się od overridine #dup, ponieważ nie jestem "przypuszczalnie" i przesłonić #clone za pomocą metody płytkich kopii?

Zapraszam do komentowania powyższych słów, ale załóżmy, że zastąpię #dup. Mogłem zrobić tylko to:

class Pointer 
    def dup; self.class.new(contents) end 
end 

Ale on-line, czytałem coś podobnego „na dup metody będzie nazywamy zainicjować skopiować metoda”. Ponadto, this guy pisze o Ruben w następujących wersjach: #initialize_clone, #initialize_dup i #initialize_copy. Zastanawiam się, czy jest to najlepsza praktyka?

class Pointer 
    def initialize_copy 
    # do I don't know what 
    end 
end 

Lubisz to?

class Pointer 
    def initialize_dup 
    # do I don't know what 
    end 
end 

czy mam po prostu zapomnieć o tyrady internetowych pisanych mylić początkujących i przejść do nadrzędnych #dup bez obaw?

Również rozumiem, że mogę po prostu zadzwonić #dup bez definiowania niestandardowych #dup, ale co jeśli chcę definiować #dup z różnych zachowań?

Również to samo pytanie dotyczy #clone - czy powinienem spróbować zdefiniować #initialize_clone lub po prostu #clone?

+0

Mogę zapytać dlaczego robisz klasę wskaźnika w ogóle ? Zmienne Ruby są już referencjami/wskaźnikami. –

+0

Czasami chcesz zaimplementować własną strukturę danych lub chcesz, aby wskaźnik wykonywał sztuczki. Nie chodzi o to, czy klasa jest wskaźnikiem czy czymś innym, ale jeśli musisz wiedzieć, interesują mnie struktury Zza Teda Nelsona, a Ted określa to, co nazywa "kursorami", więc zdecydowałem się je nazwać "punktami" "jak w Emacs. Wiesz, musisz zaimplementować klasę wskaźnika, gdy wymaga tego specyfikacja struktury danych. –

Odpowiedz

16

Z mojego doświadczenia wynika, że ​​przeciążanie #initialize_copy działa dobrze (nigdy nie słyszałem o initialize_dup i initialize_clone).

Oryginalny initialize_copy (który inicjuje każde wystąpienie zmiennej z wartościami z oryginalnego obiektu) jest dostępna za pośrednictwem Super, więc zazwyczaj robię:

class MyClass 
    def initialize_copy(orig) 
    super 
    # Do custom initialization for self 
    end 
end 
+0

Jak to się dzieje w przypadku ponownego definiowania #dup? Czy to kiedykolwiek o.k. przedefiniować #dup? –

+3

Duża różnica polega na tym, że po ponownym zdefiniowaniu #dup, "self" jest oryginalnym obiektem.Dlatego nie masz dostępu do wewnętrznego stanu nowego obiektu. Jest odwrotnie w #initialize_copy –

+2

Jeszcze jedna różnica: nauczyłem się na własnej skórze, że w implementacji Ruby w języku Matz niektóre funkcje C wywołują np. rb_obj_dup bezpośrednio zamiast korzystania z normalnej wysyłki metody. #dup może być jednym z nich. Co oznacza, że ​​niektóre standardowe biblioteki rzeczy * nie * wywoływałyby twojej wersji #dup podczas gdy * to * wywoływałoby #initialize_copy –

Powiązane problemy