# Instance variable acting like class variable?

**URL:** <https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152>\
**Category:** Ruby\
**Created:** [September 21, 2008, 9:55pm UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152 "2008-09-21T21:55:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cobra050](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/3d9bf3/32.png) [@cobra050](https://www.ruby-forum.com/u/cobra050)\
**Post date:** [September 21, 2008, 9:55pm UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152/1 "2008-09-21T21:55:56Z")

</div>

I’ve written a Node class that I’m using to write a few programs for in  
a course.

class Node

# A node represents a spot on the grid. It knows its

# location and parent node, the total cost so far, and

# the directions take to get to current location

attr\_reader :row, :col, :cost, :direction, :parent, :collected

def initialize(row, col, cost, direction=nil, parent=nil)  
@row = row  
@col = col  
@cost = (parent.nil? ? 0.0 : parent.cost) + cost.to\_i  
@direction = (parent.nil?) ? “” : parent.direction + direction  
@parent = parent  
@collected = (parent.nil?) ? [] : parent.collected.to\_a  
end

def to\_s  
“row:#{@row} col:#{@col} cost:#{@cost}”  
end

def location  
[@row, @col]  
end

def add\_collected  
@collected = @collected \<\< [[@row, @col]]  
end  
end

The problem is with #add\_collected. When it is called its updating  
@collected for all instances of Node. @collected is suppose to be an  
array of arrays. I’m not sure why it’s behaving the way that it is. I’m  
still a bit new to ruby. Can anyone give me some insight on why its  
behaving the way that it is please. Thanks.

---

<div class="post-metadata">

**Author:** ![cobra050](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/3d9bf3/32.png) [@cobra050](https://www.ruby-forum.com/u/cobra050)\
**Post date:** [September 21, 2008, 10:04pm UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152/2 "2008-09-21T22:04:50Z")

</div>

Mike Jo wrote:

> The problem is with #add\_collected. When it is called its updating  
> @collected for all instances of Node. @collected is suppose to be an  
> array of arrays. I’m not sure why it’s behaving the way that it is. I’m  
> still a bit new to ruby. Can anyone give me some insight on why its  
> behaving the way that it is please. Thanks.

1. The method \<\< is an in-place modifier, you don’t have to assign the  
result, you just write array\<\<elem and it adds elem to array.

2. If @collected is going to be an array of two-element arrays, then you  
should write @collected\<\<[@row,@col] - only one pair of square brackets.  
This is because the \<\< method treats the object on the right as an  
element and does not check if it is or is not an array. Check it  
yourself in irb:  
irb(main):010:0\> a=[]  
=\> []  
irb(main):011:0\> a\<\<[1,2]  
=\> [[1, 2]]  
irb(main):012:0\> a\<\<[2,5]  
=\> [[1, 2], [2, 5]]

3. My guess for your main problem is that you create just one instance  
of Node and then assign it to all the places where you want to keep your  
nodes. If you create your nodes like this:  
nodes=Array::new(num\_nodes,Node::new(args)) then this is the case - you  
create one node and populate the array with pointers to the node. (The  
correct solution would be nodes=Array::new(num\_nodes){Node::new(args)}  
because this form calls the block for each newly created elements, so  
you’d have num\_nodes separate nodes.) But it’s just my guess, you’d have  
to post your code that creates the nodes to verify it.

TPR.

---

<div class="post-metadata">

**Author:** ![cobra050](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/3d9bf3/32.png) [@cobra050](https://www.ruby-forum.com/u/cobra050)\
**Post date:** [September 21, 2008, 10:32pm UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152/3 "2008-09-21T22:32:48Z")

</div>

Thomas B. wrote:

> 1. My guess for your main problem is that you create just one instance  
> of Node and then assign it to all the places where you want to keep your  
> nodes. If you create your nodes like this:  
> nodes=Array::new(num\_nodes,Node::new(args)) then this is the case - you  
> create one node and populate the array with pointers to the node. (The  
> correct solution would be nodes=Array::new(num\_nodes){Node::new(args)}  
> because this form calls the block for each newly created elements, so  
> you’d have num\_nodes separate nodes.) But it’s just my guess, you’d have  
> to post your code that creates the nodes to verify it.
> 
> TPR.

I do have an array of Node objects, but I’m calling Node.new(args) each  
times I add a node to the array.

Example:

@nodes = Array.new  
@nodes \<\< Node.new(args)

---

<div class="post-metadata">

**Author:** ![cobra050](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/3d9bf3/32.png) [@cobra050](https://www.ruby-forum.com/u/cobra050)\
**Post date:** [September 22, 2008, 12:23am UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152/4 "2008-09-22T00:23:01Z")

</div>

Rick Denatale wrote:

> Every instance of Node will have it’s own instance variable, BUT
> 
> assume that you do
> 
> ```
> n1 = Node.new(r1, c1, cost1, direction1)
> n2 = Node.new(r2, c2, cost2, direction2, n1)
> 
> ```
> 
> Now since Array#to\_a returns self (i.e. the same array), n2.collected  
> will  
> refer to exactly the same array as n1.collected, and so any changes to  
> the  
> object will be visible through either instance variable.
> 
> If you change the parent.collected.to\_a to parent\_collected.dup then it  
> will  
> break this alias by making a shallow copy of the parents array at the  
> time  
> of initialization, but, not knowing what you are trying to do, this  
> might or  
> might not fix your actual problem.
> 
> –  
> Rick DeNatale

Rick,  
That was exactly what I needed. Thank you!

---

<div class="post-metadata">

**Author:** ![cobra050](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/3d9bf3/32.png) [@cobra050](https://www.ruby-forum.com/u/cobra050)\
**Post date:** [September 22, 2008, 12:08am UTC](https://www.ruby-forum.com/t/instance-variable-acting-like-class-variable/149152/5 "2008-09-22T00:08:33Z")

</div>

On Sun, Sep 21, 2008 at 3:47 PM, Mike Mr. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’ve written a Node class that I’m using to write a few programs for in  
> a course.
> 
> class Node  
> #…
> 
> def initialize(row, col, cost, direction=nil, parent=nil)  
> #…

@collected = (parent.nil?) ? [] : parent.collected.to\_a

> end
> 
> The problem is with #add\_collected. When it is called its updating  
> @collected for all instances of Node.

You are confusing the instance variable @collected with the object it  
references.

Every instance of Node will have it’s own instance variable, BUT

assume that you do

```
n1 = Node.new(r1, c1, cost1, direction1)
n2 = Node.new(r2, c2, cost2, direction2, n1)

```

Now since Array#to\_a returns self (i.e. the same array), n2.collected  
will  
refer to exactly the same array as n1.collected, and so any changes to  
the  
object will be visible through either instance variable.

If you change the parent.collected.to\_a to parent\_collected.dup then it  
will  
break this alias by making a shallow copy of the parents array at the  
time  
of initialization, but, not knowing what you are trying to do, this  
might or  
might not fix your actual problem.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
