Enrique Moreno Tent
Enrique Moreno Tent

Reputation: 25267

Instance variables: belonging to class Object vs belonging to instances

I was looking at some Ruby documentation, and I found the following:

class MyClass
  @one = 1

  def do_something
    @one = 2
  end

  def output
    puts @one
  end
end

instance = MyClass.new
instance.output
instance.do_something
instance.output

Surprisingly, this outputs:

nil
2

The explanation in the documentation was following:

This happens (nil in the first output line) because @one defined below class MyClass is an instance variable belonging to the class object (note this is not the same as a class variable and could not be referred to as @@one), whereas @one defined inside the do_something method is an instance variable belonging to instances of MyClass. They are two distinct variables and the first is accessible only in a class method.

I did not understand this explanation... So far all I got is that there are:

  1. Class variables, similar to static attributes in other languages. This is clear.
  2. Instance variables belonging to the class object
  3. Instance variables belonging to the instances

I dont get point 2 & 3

Point 2 sounds like point 1, except that is says explicitly it is not. Point 3 sounds like the normal class attribute, except that it can't be defined outside a class method (??)

Can someone help me make sense of this, and maybe add some example so I can see the use of the existence of these 3 types of variables?

Upvotes: 0

Views: 81

Answers (2)

sawa
sawa

Reputation: 168101

Given the assignment:

class MyClass
  @@class_variable = 3
  @class_instance_variable = 1
  def initialize
    @instance_variable = 2
  end
end

the visibility is like this:

class MyClass
  def my_instance_method
    @@class_variable         # => Can refer (`3`)
    @class_instance_variable # => Cannot refer (`nil`)
    @instance_variable       # => Can refer (`2`)
  end
  def self.my_singleton_method
    @@class_variable         # => Can refer (`3`)
    @class_instance_variable # => Can refer (`1`)
    @instance_variable       # => Cannot refer (`nil`)
  end
  @@class_variable           # => Can refer (`3`)
  @class_instance_variable   # => Can refer (`1`)
  @instance_variable         # => Cannot refer (`nil`)
end

class SubClass < MyClass
  def my_instance_method
    @@class_variable         # => Can refer (`3`)
    @class_instance_variable # => Cannot refer (`nil`)
    @instance_variable       # => Cannot refer (`nil`)
  end
  def self.my_singleton_method
    @@class_variable         # => Can refer (`3`)
    @class_instance_variable # => Cannot refer (`nil`)
    @instance_variable       # => Cannot refer (`nil`)
  end
  @@class_variable           # => Can refer (`3`)
  @class_instance_variable   # => Cannot refer (`nil`)
  @instance_variable         # => Cannot refer (`nil`)
end

Upvotes: 2

J&#246;rg W Mittag
J&#246;rg W Mittag

Reputation: 369458

Instance variables belong to instances (aka objects). Each object has its own instance variables.

There are two objects in the code above: instance and MyClass. Each of those objects has its own set of instance variables.

MyClass has an instance variable called @one, which is initialized to 1.

The first time output is called, instance doesn't have an instance variable called @one, but that's okay: un-initialized and undefined instance variables don't raise exceptions, they simply evaluate to nil. When do_something is called, instance's instance variable @one is created automatically (instance variables magically spring into existence the first time they are assigned) and initialized to 2, so that the second time output is called, it now prints 2.

MyClass's instance variable @one is a red herring, it is never accessed in the code above (after line 2 where it is created and initialized, of course).

Class Variables are denoted with a double-at @@ sigil. They belong to a class (actually, a module) and are shared between all subclasses, all instances, all instances of all subclasses, all sub-subclasses, all instances of all sub-subclasses and so on. They should be rather thought of as a (slightly) restricted form of global variables.

Upvotes: 3

Related Questions