在Ruby的文档的dup
说:
在一般情况下,
clone
并dup
可能在派生类不同的语义.虽然clone
用于复制对象(包括其内部状态),但dup
通常使用后代对象的类来创建新实例.
但是当我做一些测试时,我发现它们实际上是相同的:
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7
Run Code Online (Sandbox Code Playgroud)
那么这两种方法有什么区别?
Jer*_*man 296
子类可以重写这些方法以提供不同的语义.在Object
本身,有两个关键区别.
首先,clone
复制单例类,而dup
不是.
o = Object.new
def o.foo
42
end
o.dup.foo # raises NoMethodError
o.clone.foo # returns 42
Run Code Online (Sandbox Code Playgroud)
第二,clone
保留冷冻状态,而不保留dup
.
class Foo
attr_accessor :bar
end
o = Foo.new
o.freeze
o.dup.bar = 10 # succeeds
o.clone.bar = 10 # raises RuntimeError
Run Code Online (Sandbox Code Playgroud)
这些方法的Rubinius实现 通常是我对这些问题的答案的来源,因为它非常清楚,并且是一个相当兼容的Ruby实现.
jva*_*nen 186
处理ActiveRecord时也存在显着差异:
dup
创建一个没有设置id的新对象,这样你就可以通过点击将新对象保存到数据库中 .save
category2 = category.dup
#=> #<Category id: nil, name: "Favorites">
Run Code Online (Sandbox Code Playgroud)
clone
创建一个具有相同id的新对象,因此对该新对象所做的所有更改都将覆盖原始记录(如果按下) .save
category2 = category.clone
#=> #<Category id: 1, name: "Favorites">
Run Code Online (Sandbox Code Playgroud)
Jon*_*eim 30
一个区别是冷冻物体.在clone
一个冻结对象的也冻结(而dup
冻结对象的不是).
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
x.freeze
y = x.dup
z = x.clone
y.x = 5 => 5
z.x = 5 => TypeError: can't modify frozen object
Run Code Online (Sandbox Code Playgroud)
另一个区别在于单身方法.同样的故事,dup
不会复制那些,但clone
确实如此.
def x.cool_method
puts "Goodbye Space!"
end
y = x.dup
z = x.clone
y.cool_method => NoMethodError: undefined method `cool_method'
z.cool_method => Goodbye Space!
Run Code Online (Sandbox Code Playgroud)
在新的文档包含一个很好的例子:
class Klass
attr_accessor :str
end
module Foo
def foo; 'foo'; end
end
s1 = Klass.new #=> #<Klass:0x401b3a38>
s1.extend(Foo) #=> #<Klass:0x401b3a38>
s1.foo #=> "foo"
s2 = s1.clone #=> #<Klass:0x401b3a38>
s2.foo #=> "foo"
s3 = s1.dup #=> #<Klass:0x401b3a38>
s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
82553 次 |
最近记录: |