我做了一些搜索,发现了一些关于创建深度复制操作符的不同方法和帖子。
是否有一种快速简便的(内置)方式来深入复制Ruby中的对象?字段不是数组或散列。
在Ruby 1.9.2中工作。
深层副本不是内置于vanilla Ruby中,但您可以通过编组和解组对象来破解它:
Marshal.load(Marshal.dump(@object))
但这并不完美,并不适用于所有对象。一种更健壮的方法:
class Object
def deep_clone
return @deep_cloning_obj if @deep_cloning
@deep_cloning_obj = clone
@deep_cloning_obj.instance_variables.each do |var|
val = @deep_cloning_obj.instance_variable_get(var)
begin
@deep_cloning = true
val = val.deep_clone
rescue TypeError
next
ensure
@deep_cloning = false
end
@deep_cloning_obj.instance_variable_set(var, val)
end
deep_cloning_obj = @deep_cloning_obj
@deep_cloning_obj = nil
deep_cloning_obj
end
end
资源:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43424
Rails有一个名为deep_dup
的递归方法,它将返回一个对象的深层副本,而与dup
和clone
相反,它甚至可以在复合对象上工作(数组/哈希的数组/哈希)。它很简单:
def deep_dup
map { |it| it.deep_dup }
end
有一个本机实现来执行ruby对象的深度克隆:ruby_deep_clone
用gem安装:
gem install ruby_deep_clone
用法示例:
require "deep_clone"
object = SomeComplexClass.new()
cloned_object = DeepClone.clone(object)
它比Marshal方法快6到7倍,事件与冻结物体一起使用。
你可以使用重复的宝石。
它是一个小的纯ruby gem,能够递归地复制对象它也会将它的对象引用复制到新的复制中。
require 'duplicate'
duplicate('target object')
我建议你使用ActiveSupport gem,它会为你的原生Ruby核心添加大量的糖,而不仅仅是一个deep clone方法。
您可以查看documentation以获取有关已添加方法的更多信息。
自动深度克隆并不总是你想要的。通常,您需要定义选定的几个属性以进行深度克隆。一种灵活的方法是实现initialize_copy
,initialize_dup
和initialize_clone
方法。
如果你有一个班级:
class Foo
attr_accessor :a, :b
end
并且你只想深度克隆:b
,你重写initialize_*
方法:
class Foo
attr_accessor :a, :b
def initialize_dup(source)
@b = @b.dup
super
end
end
当然,如果你想让@b
深入克隆它自己的一些属性,你也可以在b的类中做同样的事情。
为了更完整的解释,我从这篇文章https://aaronlasseigne.com/2014/07/20/know-ruby-clone-and-dup/中学到了这一点
还可以查看deep_dive。这允许您对对象图进行受控深度复制。
你真的不需要宝石。这不可能比这更简单,这不值得宝石的开销!
def deep_clone(obj)
obj.clone.tap do |new_obj|
new_obj.each do |key, val|
new_obj[key] = deep_clone(val) if val.is_a?(Hash)
end
end
end