📜 ⬆️ ⬇️

Class-level instance variables

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 # => [] o1.get_a # => nil o1.set_a 123 o1.instance_variables # => ["@a"] o1.get_a # => 123 o2 = A.new o2.get_a # => nil 


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 #    : self.class.attr_accessor :a #   ,  attr_accessor  private method :( end A.instance_variables # => ["@a"] A.class_variables # => [] Aa # => nil Aa = 123 Aa # => 123 


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-ruby
wiseheartdesign.com/articles/2006/09/22/class-level-instance-variables
snippets.dzone.com/posts/show/4382

Dear readers, if it is not difficult, add more related links here so that you can use this material as an educational topic.

Source: https://habr.com/ru/post/111781/


All Articles