为什么Ruby中没有深层复制方法?

我正在研究技术图纸(svg / ruby​​)的解决方案。 我想操纵矩形,并add! 这个类中的方法:

 class Rect def add!(delta) @x1+=delta ... # and so on self end end 

我还需要一个返回Rectadd方法,但不需要操作self

 def add(delta) r=self.dup/clone/"copy" # <-- not realy the 3 and no quotes, just in text here r.add! delta end 

dupclone不做我的事情,但是:

 def copy; Marshal.load(Marshal.dump(self)); end 

确实。

为什么普通Ruby中不存在这样的基本function? 请不要告诉我,我可以反向addadd! ,让add完成工作,并add! 叫它。

我不确定为什么在Ruby中没有深度复制方法,但我会尝试根据我能找到的信息进行有根据的猜测(参见该行下面的链接和引号)。

从这些信息来看,我只能推断Ruby没有深度复制方法的原因是因为它很少需要,并且在少数情况下确实需要,还有其他相对简单的方法来完成相同的任务:

如您所知,目前使用Marshal.dumpMarshal.load是推荐的方法。 这也是Programming Ruby推荐的方法(参见下面的摘录)。

或者,在这些gem中至少有3个可用的实现: deep_cloneabledeep_cloneruby_deep_clone ; 第一个是最受欢迎的。


相关信息

这是对comp.lang.ruby的讨论 ,可能会对此有所了解。 这里有另一个答案与一些相关的讨论,但这一切都回到使用Marshal

在编程Ruby中没有提到深度复制,但在Ruby编程语言中有一些提及。 以下是一些相关的摘录:

[…]

Marshal.dumpMarshal.load另一个用途是创建对象的深层副本:

 def deepcopy(o) Marshal.load(Marshal.dump(o)) end 

[…]

Marshal.dumpMarshal.load使用的二进制格式依赖于版本,并且不保证较新版本的Ruby能够读取旧版本Ruby编写的编组对象。

[…]

请注意,文件和I / O流以及Method和Binding对象太动态,无法编组; 没有可靠的方法来恢复他们的状态。

[…]

不要对数组进行防御性深层复制,只需在其上调用to_enum ,然后传递生成的枚举数而不是数组本身。 实际上,您正在为数组创建一个可枚举但不可变的代理对象。

忘记编组。 deep_dive gem将解决您的问题。

https://rubygems.org/gems/deep_dive

为什么你不能使用这样的东西:

 new_item = Item.new(old_item.attributes) new_item.save! 

这会将所有属性从现有项复制到新项,而不会出现问题。 如果您有其他对象,则可以单独复制它们。

我认为这是复制对象的最快方法