On Jan 9, 2008 3:35 PM, Daniele Antani <daniele.cesarini / gmail.com> wrote:
> 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?

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.