Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically added instance method can not access class variable [duplicate]

Tags:

ruby

(Question already posted at Ruby Forum, but did not evoke any answer there).

This is my code:

class MC
  def initialize
    @x = 5
    @@y = 6
  end

  def f
    puts @x
    puts @@y
  end
end

m = MC.new
m.f

m.f produces the expected output without an error:

5
6

But this:

def m.g
  puts @x
  puts @@y
end

m.g

produces:

5
warning: class variable access from toplevel
NameError: uninitialized class variable @@y in Object

Why can I access @@y from f, but not from g?

Mentioning of toplevel and Object in the warning and the error message is puzzling to me.

@x is printed as 5, so its environment is MC. This excludes the possibility that @x and @@y in the definition of m.g refer to the toplevel environment (Object) instead of MC.

Why did I get the error message?

like image 772
user1934428 Avatar asked Mar 08 '16 07:03

user1934428


2 Answers

All variants below work:

def m.g; puts self.class.send(:class_eval, '@@y') end

def m.g; puts self.class.class_variable_get(:@@y) end

class << m; def g; puts self.class.send(:class_eval, '@@y') end end

class << m; puts class_variable_get(:@@y) end

But these fail:

def m.g; puts @@y; end

class << m; puts class_eval('@@y') end

I would consider this being a ruby parser glitch.

like image 112
Aleksei Matiushkin Avatar answered Sep 28 '22 03:09

Aleksei Matiushkin


You do not create g in the class MC but in m's singleton class (a.k.a. eigenclass).

This is a class existing specifically for the object m to store the singleton methods that are defined just for m.

like image 38
undur_gongor Avatar answered Sep 28 '22 03:09

undur_gongor