2016-03-08 119 views
6

(问题已发布在Ruby Forum,但没有在那里引起任何答案)。动态添加实例方法无法访问类变量

这是我的代码:

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

    def f 
    puts @x 
    puts @@y 
    end 
end 

m = MC.new 
m.f 

m.f产生预期的输出没有错误:

5 
6 

但这:

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

m.g 

生产:

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

为什么我可以从f访问@@y,但不能从g访问?

在提示中提到toplevelObject,错误信息令我费解。

@x打印为5,所以其环境为MC。这排除了m.g的定义中的@x@@y参考顶级环境(Object)而不是MC的可能性。

为什么我收到错误信息?

+3

这是之前问过的:http://stackoverflow.com/q/24510948/477037 – Stefan

+1

@Stefan:是的。不幸的是,这里也没有很好的解释。 –

回答

4

您不会在类0123B中创建g,而是在m的单例类(也称为特征类)中创建g

这是专门为对象m存在的类,用于存储仅为m定义的单例方法。

+0

'class << m;把class_variable_get(:@@ y);完美“的作品。除了'def m.g;放置self.class.class_variable_get(:@@ y); end'。这有点奇怪。 – mudasobwa

+0

请注意,这只是答案的一部分。 singleton类是MC的一个子类('m.singleton_class.superclass#=> MC'),因此它“看到”@@ y'('m.singleton_class.class_variables#=> [:@yy]' )。我错过了查找失败的原因。 –

+0

我想这是一个解析器故障。 – mudasobwa

5

以下工作全部变型:

​​

但是这些失败:

def m.g; puts @@y; end 

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

我会认为这是一个ruby解析器毛刺。

+0

请注意'#class'方法“跳过”单例类并返回'MC'。所以前3个并不令人惊讶。您还应该添加带有'singleton_class'的变体,它们显示相同的行为。 –

+1

似乎常量查找的规则也适用于类变量,即它们在词汇范围内。 – Stefan

+0

@undur_gongor'class << m'是带有'singleton_class'的变体。 – mudasobwa