Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read a class's instance variable scope and visibility

Tags:

ruby

Why is it not possible to read a class's instance variable value if it was set within the class using the attr_accessor?

Is it because the the instance variable is "private?"

Setting the attribute this way works:

class Test
  attr_accessor :magic
end

bob = Test.new
bob.magic = "cat" #set 
print bob.magic #read

Setting the attribute this way fails:

class Test
  attr_accessor :magic
  @magic = "spell"
end

bob = Test.new
print bob.magic #this resolves to 'nil'
like image 814
brooklynsweb Avatar asked May 14 '26 20:05

brooklynsweb


1 Answers

There is a significant difference between instance variables and class instance variables.

class Test
  @magic = "spell" # class instance var, since the scope is class 

  def initialize
    @magic = 42 # instance var, scope is instance
  end
end

Those two live together, since they are defined on different objects:

Test.instance_variable_get(:@magic) #⇒ "spell"
Test.new.instance_variable_get(:@magic) #⇒ 42

That said, attr_accessor reads the variable from the scope, it was defined for. Yours was defined in class scope, therefore it reads the instance scoped variable.

To read the class instance variable, define attr_accessor on class’ singleton class level:

class Test
  singleton_class.send :attr_accessor, :magic # reads class instance var ⇓
  @magic = "spell" # class instance var, since the scope is class 

  attr_accessor :magic # reads instance var ⇓
  def initialize
    @magic = 42 # instance var, scope is instance
  end
end

Test.magic
#⇒ "spell"
Test.new.magic
#⇒ 42
like image 193
Aleksei Matiushkin Avatar answered May 16 '26 08:05

Aleksei Matiushkin