【问题标题】:Ruby: attr_accessor method undefined when called in an outside moduleRuby:在外部模块中调用时未定义 attr_accessor 方法
【发布时间】:2019-01-26 05:19:26
【问题描述】:

我在模块中定义了一个 ruby​​ 类,如下所示

module Foo
    class Bar
        attr_accessor :attr_1, :attr_2, :attr_3

        def initialize
            @attr_1 = "a"
            @attr_2 = "b"
            @attr_3 = "c"
        end

    end
end

然后我尝试在一个单独的模块中访问实例变量(或 attr_accessor 定义的 getter),如下所示:

module AccessingModule

    def get_instance_variables
        var_1 = Foo::Bar.attr_1
        var_2 = Foo::Bar.attr_2
        var_3 = Foo::Bar.attr_3

    end

 end

尝试调用 var_1 = Foo::Bar.attr_1 时,我收到错误 NoMethodError: undefined method attr_1 for Foo::Bar:Class

有谁知道是什么阻止我访问 attr_accessor 中定义的内容?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    您正在 initialize 方法中分配实例变量。但在模块中,您尝试在 Foo::Bar 上调用类方法。

    你需要先创建Foo::Bar的实例,然后调用实例上的getter方法:

    module AccessingModule
      def get_instance_variables
        foo_bar = Foo::Bar.instance # get the Singleton instance of `Foo::Bar`
    
        var_1 = foo_bar.attr_1
        var_2 = foo_bar.attr_2
        var_3 = foo_bar.attr_3
      end
    end
    

    【讨论】:

    • 感谢您的评论。 @spickermann 我在下面留下了类似的评论,但是当我尝试实例化 Foo::Bar 时,我收到错误 cannot access private method new
    • 我无法使用示例中的类重现 Foo::Bar.new 引发此类错误。代码中没有任何内容使该方法成为私有的。您确定您的示例包含所有相关代码吗?
    • 我遗漏的两件事是 Foo::Bar 包含 Singleton 和模块 AccessingModule 扩展 ActiveSupport::Concern。这两件事会有所不同吗?
    • 是的,确实如此。因为include Singletonnew 方法设为私有。在这种情况下,您必须使用instance 而不是new 来获取一个单例实例,而不是每次都使用new 创建新的(不同的)实例。请参阅:How to Use The Singleton Pattern。我更新了我的答案来解决这个问题。
    【解决方案2】:

    您正在尝试访问实例变量而不实例化Foo::Bar 对象。先创建Foo::Bar的实例,然后就可以访问attr_1attr_2...

    bar = Foo::Bar.new
    
    bar.attr_1 # => 'a'
    

    现在,如果你想在不实例化对象的情况下访问属性,你需要将它们定义为类变量:

    module Foo
      class Bar
        @@attr_1 = 'a'
    
        def self.attr_1
          @@attr_1
        end
      end
    end
    
    Foo::Bar.attr_1 # => 'a'
    

    如果您不知道实例和类变量是什么,请阅读this post

    【讨论】:

    • 感谢您的回复。当我尝试实例化一个新对象时,我遇到了cannot access private method new 的错误。
    • @samiam0906 您发布的代码对我有用。这就是你的全部代码吗?
    • 我遗漏的两件事是 Foo::Bar 包含 Singleton 和模块 AccessingModule 扩展 ActiveSupport::Concern。这两件事会有所不同吗?
    • @samiam0906 我对 Singleton 不是很熟悉,但我知道它确实会引发 NoMethodError: private method 'new' called for Foo::Bar 并且它被认为是一种反模式。您确定需要使用它吗?
    • 当我删除 Singleton 包含时,我可以在课堂上调用 new。我要创建的类应该是单例,但也许有一种解决方法,而不使用单例声明。
    猜你喜欢
    • 1970-01-01
    • 2013-01-30
    • 2014-02-21
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2022-07-01
    相关资源
    最近更新 更多