2017-02-01 31 views
1

我有一個模塊,它包含實例方法和包含在類中的類方法。實例方法和類方法都將訪問類變量。在模塊類和實例方法中訪問類變量

module MyModule 
    @@a_class_variable = "lorem ipsum" 

    def self.included(base) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def a_class_method 
     @@a_class_variable << "abc" 
    end 
    end 

    # Use it in constructor 
    def initialize 
    @@a_class_variable << "abc" 
    end 

    def an_instance_method 
    @@a_class_variable << "abc" 
    end 
end 

當我包括一些類MyModule,解釋說:NameError:在MyModule中:: ClassMethods未初始化的類變量@@ a_class_method

我在做什麼錯?

回答

0

當進入MyModule::ClassMethods時,您不在MyModule之內,並且無權訪問@@a_class_variableHere's有關的問題。

與訪問者,你的代碼工作正常:

module MyModule 
    @@a_class_variable = "lorem ipsum" 

    def self.a_class_variable 
    @@a_class_variable 
    end 

    def self.included(base) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def a_class_method 
     MyModule.a_class_variable << " abc1" 
    end 
    end 

    # Use it in constructor 
    def initialize 
    @@a_class_variable << " abc2" 
    end 

    def an_instance_method 
    @@a_class_variable << " abc3" 
    end 
end 

class MyObject 
    include MyModule 
end 

my_object = MyObject.new 
MyObject.a_class_method 
p my_object.an_instance_method 
#=> "lorem ipsum abc2 abc1 abc3" 

當您在評論中指出,它暴露@@a_class_variable給公衆。 將方法設置爲privateprotected在以上示例中不起作用,因爲ClassMethodsMyModule不相關。

它可能不是最乾淨的解決方案,但你可以使用send訪問私有方法:

module MyModule 
    @@a_class_variable = 'lorem ipsum' 

    module ClassMethods 
    def a_class_method 
     MyModule.send(:__a_class_variable) << ' abc1' 
    end 
    end 

    # Use it in constructor 
    def initialize 
    @@a_class_variable << ' abc2' 
    end 

    def an_instance_method 
    @@a_class_variable << ' abc3' 
    end 

    class << self 
    def included(base) 
     base.extend ClassMethods 
    end 

    private 

    def __a_class_variable 
     @@a_class_variable 
    end 
    end 
end 
+0

謝謝您的回答!這確實可以運行,但它暴露了類變量給公衆。有沒有保留功能和保持訪問類變量私人,是嗎?因爲當我在一個類中時,我可以直接從實例和類方法中訪問任何類變量。 – nsommer

+0

你是完全正確的。我更新了答案。 –

+0

我想我現在明白了def sef.something; ClassMethods中的方法和方法的區別。我認爲沒有什麼區別,但有。我還從rails中查找了部分代碼(例如ActiveSupport中的回調函數),看起來他們完全按照您的建議(訪問器方法)實現了內容。我之前試圖理解它,但直到現在我都失敗了。總而言之,這不是我所希望的(閱讀:代碼並不像我希望的那樣美),但那不是你的錯,所以我會接受答案。 – nsommer