2014-07-02 20 views
0

尋找一個解釋,爲什麼在Module.class_eval塊下面的例子中,類變量查找不工作:class_eval和類變量的上下文嗎?

class MyClass 
    @@myvar = 123 
    def self.myvar_getter 
    @@myvar 
    end 
end 

class MyClass 
    p "#{self}, #{self.object_id}, #{singleton_class.object_id}" 
    # output: "MyClass, 21055520, 21055500" 
    p myvar_getter # class method lookup working 
    # output: 123 
    p @@myvar  # class variable lookup working 
    # output: 123 
end 

MyClass.class_eval do 
    p "#{self}, #{self.object_id}, #{singleton_class.object_id}" 
    # output: "MyClass, 21055520, 21055500" 
    p myvar_getter # class method lookup working as expected 
    # output: 123 
    p @@myvar  # class variable lookup NOT working (why ?) 
    # output: -- following exception -- 
    # a.rb:47: warning: class variable access from toplevel 
    # a.rb:47:in `block in <main>': uninitialized class variable 
    # @@myvar in Object (NameError) 
end 

正如你可以看到的範圍似乎是相同的,self是一樣的,類方法:myvar_getter被發現在這兩種情況下,但在class_eval塊內Object類別中意外地查找類別變量@@myvar。 除了之外,任何人都可以解釋這種行爲嗎,因爲

+1

我想這裏的教訓是,類變量幾乎不會按照您希望的方式運行。如果您已經習慣使用它們,那麼您可以通過在所討論的類上明確使用'class_variable_get/set'來找到更一致的結果。 –

+0

@IronSavior感謝您的評論。我知道'class_variable_get/set'方法。我甚至讀過耶胡達卡茨關於[Ruby中的元編程]的偉大文章(http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/),其中描述了範圍,方法解析和方法定義之間的細微差別。但是這個問題沒有解釋問題。是否還有另一個區分變量查找的概念? –

+0

[使用類\ _eval和實例\ _eval訪問Ruby類變量](http://stackoverflow.com/questions/3434884/accessing-ruby-class-variables-with-class-eval-and-instance-eval ) – infused

回答

0

我不得不經歷一些微弱的時刻,因爲回答很清楚&顯而易見。

Module.class_eval文檔:

求值,不同的是當給出 塊,常數/類變量查找不受影響國防部,的上下文中的字符串或塊。這可以是用於將方法添加到類的 。 module_eval返回評估 其參數的結果。 (即不使用類變量的getter/setter方法)

所以,如果我需要直接從eval塊訪問類變量,我只是通過代碼字符串:

MyClass.class_eval <<-EOS 
    p @@myvar  # class variable lookup is working from a string 
    # output: 123 voila! 
    EOS