2014-09-10 1 views
0

я наткнулся на следующую озабоченность в Рубинерубин идентификатор объекта, DUP и переменчивость

a = [1, 2, 3] 
b = a 
b.delete_at(1) 
b => [1,3] 
a => [1,3] 
b.object_id => 70178446287080 
a.object_id => 70178446287080 

Так я вроде есть понимание этого. a содержит ссылку на массив на object_id.

b также имеет ссылку на этот же положении, как b указывает на a, который относится к его object_id. В основном они ссылаются на одно и то же. Так что, если я что-то мутирую для b, то также изменяется мутация a.

В какую категорию входит такое поведение? Есть ли какие-либо чтения/общие практики, которые я могу запомнить, поэтому у меня не будет никаких ошибок в будущем, связанных с этим? Я знаю, что a.dup предоставит новый объект в другом месте, так что a.dup == b будет true. Также для a.dup.object_id == b.object_id.

Кроме того, является dup и clone по существу то же самое в этой ситуации, независимо от мелкой и глубокой?

ответ

0

Оба #dup и #clone создают мелкую копию объекта. Тем не менее, #clone делает две вещи, которые #dup не:

  • копию одноэлементный класс скопированного объекта
  • поддерживать замороженное состояние скопированного объекта

Пример для одноточечного:

Факс:

a = Object.new 

def a.foo do 
    :foo 
end 

p a.foo 
# => :foo 

b = a.dup 
p b.foo 
# => undefined method `foo' for #<Object:0x007f8bc395ff00> (NoMethodError) 

#clone: ​​

a = Object.new 

def a.foo do 
    :foo 
end 

p a.foo 
# => :foo 

b = a.clone 
p b.foo 
# => :foo 

Пример замороженного состояния:

a = Object.new 

a.freeze 
p a.frozen? 
# => true 

b = a.dup 
p b.frozen? 
# => false 

c = a.clone 
p c.frozen? 
# => true 

Из-за дополнительных шагов, #clone немного медленнее, чем #dup (но это, вероятно, не то, что сделает ваше приложение слишком медленным!).

Смежные вопросы