Reputation: 25267
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:
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
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
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