Please help me to understand Class Level Instance Variables.
@@ is a class variable and is an equivalent to instance variable (@) in a class instance.
But what is an instance variable (@) when used on class level? If it puts a definition to class instance then why not to define it in an initializer?
class MyClass
cattr_reader :class_variable
def self.new_instance(cv, cliv, iv)
@@class_variable = cv
@class_level_instance_variable = cliv
self.new(iv)
end
def initialize(iv)
@instance_variable = iv
end
def use
puts "class_var=#{self.class.class_variable.inspect}\ninst_var=#{@instance_variable.inspect}\ncliv=#{@class_level_instance_variable.inspect}"
end
end
c = []
c << MyClass.new_instance(1,2,3)
c[0].use
c << MyClass.new_instance(4,5,6)
c[1].use
c << MyClass.new_instance(7,8,9)
c[2].use
c[0].use
c[1].use
c[2].use
In your answer you don't output the class level instance variable. Besides the usual syntax (@foo
), an instance variable can be accessed via a method (instance_variable_get(:@foo)
). You can use this method to read instance variables of other objects, not only self
.
Here's a modified version of your code
require 'active_support/core_ext'
class MyClass
cattr_reader :class_variable
def self.new_instance(cv, cliv, iv)
@@class_variable = cv
@class_level_instance_variable = cliv
self.new(iv)
end
def initialize(iv)
@instance_variable = iv
end
def use
puts "class_var=#{self.class.class_variable.inspect}"
puts "class inst var: #{self.class.instance_variable_get(:@class_level_instance_variable)}"
puts "inst_var=#{@instance_variable.inspect}"
end
end
c = []
c << MyClass.new_instance(1,2,3)
c << MyClass.new_instance(4,5,6)
c << MyClass.new_instance(7,8,9)
c[0].use
c[1].use
c[2].use
# >> class_var=7
# >> class inst var: 8
# >> inst_var=3
# >> class_var=7
# >> class inst var: 8
# >> inst_var=6
# >> class_var=7
# >> class inst var: 8
# >> inst_var=9
See, class inst var is always 8 (just as class var is always 7). This is because you output values after all your modifications are made. And since class level variables are shared, the last modification wins.
c << MyClass.new_instance(7,8,9)
If you were to output from initializer (as was in your first version of code), you'd see different results.
# >> class_var=1
# >> class inst var: 2
# >> inst_var=3
# >> class_var=4
# >> class inst var: 5
# >> inst_var=6
# >> class_var=7
# >> class inst var: 8
# >> inst_var=9