2012-12-31 2 views
4

나는 Ruby (MRI 1.9.3)에서 객체를 딥 복사하는 몇 가지 기법을 찾고 있습니다.
다음 예제를 보았지만 #dup 메서드 구현에 대해 확신하지 못했습니다. 테스트를 거쳤지만 제대로 작동하지만 메서드의 논리적 단계를 이해할 수 없으므로 자체 코드에서 사용하기가 쉽지 않습니다.Ruby : 객체 딥 (object deep copy)

@name = @name.dup은 내부의 iVar 을 참조하고 있습니까? 방법? 나는 그것을 볼 수 없다.

누구나 설명해 주시겠습니까?
또한 더 좋은 방법이 있습니까?

class MyClass 
    attr_accessor :name 

    def initialize(arg_str) # called on MyClass.new("string") 
    @name = arg_str   # initialize an instance variable 
    end 

    def dup 
    the_copy = super  # shallow copy calling Object.dup 
    @name = @name.dup  # new copy of istance variable 
    return the_copy   # return the copied object 
    end 
end 
+0

관련 : http://stackoverflow.com/questions/8206523/how-to-create-a-deep-copy-of-an-object-in-ruby –

답변

6

이것은 "딥 카피"의 매우 얇은 매우 구체적인 구현입니다. 이는 복제본에 독립형 @name 인스턴스 변수를 작성하여 내부 작업으로 이름을 수정해도 복제를 변경하는 부작용이 없도록하는 것입니다.

일반적으로 deep 복사 작업은 중첩 배열이나 해시와 같은 경우 중요하지만 해당 정렬을 참조하는 속성이있는 객체에도 적용 할 수 있습니다.

보다 강력한 dup 메서드를 사용하여 개체를 만들려면 각 속성에 대해 dup을 호출해야하지만이 예제는 약간 잘못되었습니다. 그것이하는 일은 원본에있는 @name을 복사본으로 대체하는 것으로 당신이 가지고있는 참조를 망칠 수 있습니다.

더 나은 버전은 다음과 같습니다

def dup 
    copy = super 
    copy.make_independent! 
    copy 
end 

def make_independent! 
    instance_variables.each do |var| 
    value = instance_variable_get(var) 

    if (value.respond_to?(:dup)) 
     instance_variable_set(var, value.dup) 
    end 
    end 
end 

이것은 dup 방법을 지원 인스턴스 변수를 복제하는 효과를 가져야한다. 이렇게하면 숫자, 부울 및 nil과 같은 항목을 건너 뛸 수 없으므로 중복 될 수 없습니다.

0

super을 수행하면 인스턴스 메서드 @name이 원본과 복제본간에 공유됩니다. @name = @name.dup을 수행함으로써 원본은 @name으로 문자열의 새 인스턴스를 가져오고 복제 된 인스턴스와 다른 @name을 갖게됩니다.