the_prole the_prole - 16 days ago 7
Ruby Question

Is .dup really creating a shallow copy?

I am having some trouble understanding the concept of a shallow copy and the

#dup
method

I have this code

class MyObject
end

myObject1 = MyObject.new
myObject2 = MyObject.new


I know this will print false becuase I am testing for object equality, not value equality

p myObject1 == myObject2


But according to the definition of a shallow copy


.dup produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference.


I had expected this to print true, but it also prints false

p myObject1 == myObject1.dup


Isn't the definition wrong then? Shouldn't
myObject1.dup
an
instance variable
that points to the same object as
myObject1
, except it's clearly not?

Answer

You forget that == is actually a method from BasicObject:

obj == other → true or false
Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

So if you haven't provided your own implementation of == (i.e. a MyObject#== method) then your:

p myObject1 == myObject1.dup

is pretty much the same as saying:

p myObject1.object_id == myObject1.dup.object_id

and since myObject1.dup is a shallow copy of myObject1 (i.e. they're different objects), you get false.

When they say:

instance variables of obj are copied

they're referring to the instance variables inside obj, not variables that happen to reference obj. Your myObject1 isn't an instance variable in anything, it is just a variable, instance variables are referenced with a leading @ as in @my_instance_variable.

If you want == to behave they way you expect it to then you have to provide your own == implementation:

class MyObject
  def ==(other)
    # Check that the contents of `self` and `other` are the same
    # and probably that `other.is_a?(MyObject)` first.
  end
end
Comments