Why this behaviour?

Hello to all,

i can’t understand the follow behaviour:

class Player
attr_accessor :hand
def initialize(hand)
@hand = hand
end
end

def roba(player)
p2 = Player.new(player.hand)
change p2
print "p2 = "
p p2
print "player = "
p player
end

def change(player)
player.hand.push(3)
end

p1 = Player.new([2, 3, 4])
roba p1

END

output is:
p2 = #<Player:0xb7c4919c @hand=[2, 3, 4, 3]>
player = #<Player:0xb7c491c4 @hand=[2, 3, 4, 3]>

Why the change affects both objects? I want to copy the first object and
work on the copy without affecting the original.

Thanks

On Jan 9, 2008 3:35 PM, Daniele A. [email protected]
wrote:

Hello to all,

i can’t understand the follow behaviour:

class Player
attr_accessor :hand
def initialize(hand)

This copies reference to the array, use #dup to create a copy (note
that it’s not recursive):

  •  @hand = hand
    
  • @hand = hand.dup
    

On Jan 9, 9:35 am, Daniele A. [email protected] wrote:

Why the change affects both objects? I want to copy the first object and
work on the copy without affecting the original.

Both Player objects contain a reference to the same array. What you
want is this:

class Player
attr_accessor :hand
def initialize(hand)
@hand = hand.clone
end
end

Daniele A. wrote:

I want to copy the first object and
work on the copy without affecting the original.

Then do that. dup copies an object. Assignment does not copy.

HTH,
Sebastian

On Jan 9, 2008 3:35 PM, Daniele A. [email protected]
wrote:

player.hand.push(3)
player = #<Player:0xb7c491c4 @hand=[2, 3, 4, 3]>

Why the change affects both objects?

Because both players point to the same array object
in their @hand variables. To see what I mean try this:

irb(main):028:0> p = Player.new([2,3,4])
=> #<Player:0xb7c16044 @hand=[2, 3, 4]>
irb(main):029:0> p.hand.object_id
=> -606031798
irb(main):030:0> p2 = Player.new(p.hand)
=> #<Player:0xb7c00b40 @hand=[2, 3, 4]>
irb(main):031:0> p2.hand.object_id
=> -606031798

So when you push an element in the array,
both hands point to the same array and you see
the change in both player objects.

I want to copy the first object and
work on the copy without affecting the original.

You can dup the array in the initialize:

def initialize(hand)
@hand = hand.dup
end

Hope this helps,

Jesus.