我正在研究技术图纸(svg / ruby)的解决方案。我想操纵矩形,并在这个类中有一个add!
方法:
class Rect
def add!(delta)
@x1+=delta
... # and so on
self
end
end
我还需要add
方法返回Rect
,但不能操纵self
:
def add(delta)
r=self.dup/clone/"copy" # <-- not realy the 3 and no quotes, just in text here
r.add! delta
end
dup
和clone
不做我的事情,但是:
def copy; Marshal.load(Marshal.dump(self)); end
确实
为什么普通Ruby中不存在这样的基本功能?请不要告诉我,我可以撤消add
和add!
,让add
完成工作,然后add!
调用它。
答案 0 :(得分:5)
我不确定为什么Ruby中没有深层复制方法,但我会尝试根据我能找到的信息进行有根据的猜测(参见该行下面的链接和引号)。
从这些信息来看,我只能推断Ruby没有深度复制方法的原因是因为它很少需要,并且在极少数情况下它确实是必要的,还有其他相对简单的方法来实现同样的任务:
如您所知,目前推荐使用Marshal.dump
和Marshal.load
来执行此操作。这也是Programming Ruby推荐的方法(参见下面的摘录)。
或者,在这些宝石中至少有3个可用的实现:deep_cloneable
,deep_clone
和ruby_deep_clone
;第一个是最受欢迎的。
相关信息
这里的a discussion over at comp.lang.ruby可能会对此有所了解。 another answer here有一些相关的讨论,但这一切都回到使用Marshal
。
在Programming Ruby中没有提及任何深度复制,但在The Ruby Programming Language中有一些提及。以下是一些相关的摘录:
[...]
Marshal.dump
和Marshal.load
的另一个用途是创建深层副本 对象:def deepcopy(o) Marshal.load(Marshal.dump(o)) end
[...]
...
Marshal.dump
和Marshal.load
使用的二进制格式是 依赖于版本,并且不保证更新版本的Ruby 能够读取旧版本Ruby编写的编组对象。[...]
请注意文件和I / O流,以及方法和绑定 物体,太动态,无法编组;没有可靠的 恢复状态的方法。
[...]
不要制作阵列的防御性深层副本,而是打电话
to_enum
就可以了,并传递生成的枚举数而不是数组 本身。实际上,您正在创建一个可枚举但不可变的代理 数组的对象。
答案 1 :(得分:1)
忘记编组。 deep_dive gem将解决您的问题。
答案 2 :(得分:0)
为什么你不能使用这样的东西:
new_item = Item.new(old_item.attributes)
new_item.save!
这会将所有属性从现有项目复制到新项目,而不会出现问题。如果您有其他对象,则可以单独复制它们。
我认为这是复制对象的最快捷方式