2016-03-08 118 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