4

Ruby(MRI 1.9.3)でオブジェクトをディープコピーするためのいくつかのテクニックを調べています。
次の例に出くわしましたが、#dupメソッドの実装についてはよくわかりません。テストして動作しましたが、メソッドの論理的な手順がわからないため、自分のコードで使用するのは快適ではありません。

ステートメントはコピー@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
4

2 に答える 2

6

これは、「ディープコピー」の非常に薄い、非常に具体的な実装です。それが示しているのは、クローン内に独立した@nameインスタンス変数を作成して、インプレース操作でインスタンス変数の名前を変更しても、クローンを変更するという副作用が発生しないようにすることです。

通常、ディープコピー操作はネストされた配列やハッシュなどにとって重要ですが、そのようなものを参照する属性を持つすべてのオブジェクトにも適用できます。

あなたの場合、より堅牢な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複製できないものをスキップします。

于 2012-12-31T17:50:25.333 に答える
0

これを行うsuperと、インスタンスメソッド@nameは元のメソッドと複製の間で共有されます。を実行することにより@name = @name.dup、オリジナルは文字列の新しいインスタンスをとして取得し、複製されたインスタンスが持っているものとは@name異なるものになります。@name

于 2012-12-31T17:52:36.893 に答える