2017-02-01 243 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