the_prole the_prole - 3 months ago 20
Ruby Question

Is .dup really creating a shallow copy?

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


I have this code

class MyObject

myObject1 =
myObject2 =

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
instance variable
that points to the same object as
, except it's clearly not?


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.