Recently there have been many publications on this topic, but newcomers again and again have questions. I publish my version of the explanation why the instance variable declared in the body of the class is not working as expected:
class User @var = 1 end
Expected behavior
Instance variables work as expected in normal situations:
class A def set_a( v ); @a = v; end def get_a; return @a; end end o1 = A.new o1.instance_variables
The variable appears in the instance after it is installed, then everything works like clockwork - it is visible only in its own instance.
')
Default value
Surprises with a variable instance usually start when you need to set its default value:
class B attr_accessor :b # set_b, get_b @b = 1 end o1 = B.new o1.b # => nil o1.instance_variables # => [] o1.b = 2 o1.b # => 2 o1.instance_variables # => ["@b"]
Op-pa. And where is our default value? Why is there no variable at all in the object from the very beginning?
Such variables are called
Class-Level Instance Variable (how is it in Russian "class-level instance variables"?)
Classes are objects.
On Ruby, that any code is executed in the context of the current object (class instance), the current object is always accessible from the
self pseudo-variable. These are basic truths. But try to answer the question, in which context (object) is line 4 and line 2?
1: class User 2: @b = 1 3: def a 4: @a = 1 5: end 6: end
Line 4 will be executed in the instance of the User class, as we expect, in the object that you create via User.new
And line 2 is executed in an instance of the Class class, in the object that describes the User class. This object will be created immediately after reading by the class interpreter User.
The very word
User is nothing more than a
consultant, the value of which is an object of type Class . This object describes our User class. The variable
@b belongs to this object.
o1 = B.new o1.b # => nil o1.instance_variables # => [] B.instance_variables # => ["@b"]
In fact, she was always there. Not in class B and not in an instance of class B, but in an instance of class Class stored in constant B.
Application
What do class instance variables give us?
They can work as personal class variables. Unlike real class variables that are available in all descendants and instances under the same name, our variable belongs only to the class in the context of which it was declared.
class B @b = 1 def self.set_b( v ); @b = v; end def self.get_b; @b; end end B.get_b # => 1 B.set_b 2 B.get_b # => 2 class B1 < B; end B1.get_b # => 1 B1.set_b 3 B1.get_b # => 3 B.get_b # => 2
That is, with each inheritance from the class in which such a variable was declared, a new independent one will be created. Compare with the behavior of a class variable:
class C @@c = 1 def self.set_c( v ); @@c = v; end def self.get_c; @@c; end end C.get_c # => 1 C.set_b 2 C.get_b # => 2 class C1 < C; end C1.get_c # => 2 C1.set_c 3 C1.get_c # => 3 C.get_c # => 3 class C2 < C; @@c = 4; end C.get_c # => 4 C1.get_c # => 4 C2.get_c # => 4
Accessors
Such variables with the help of accessors are created as follows:
class A class << self attr_accessor :a end
Note that the
cattr_accessor rail
: a will create methods with the same names, only they will refer to the class variable.
class User cattr_accessor :a end User.instance_variables # => [] User.class_variables # => ["@@a"]
Materials on the topic:
railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-rubywiseheartdesign.com/articles/2006/09/22/class-level-instance-variablessnippets.dzone.com/posts/show/4382Dear readers, if it is not difficult, add more related links here so that you can use this material as an educational topic.