【问题标题】:Ruby Module can't access local variableRuby 模块无法访问局部变量
【发布时间】:2017-03-24 03:42:04
【问题描述】:

是否可以从GetVar.print_foo 访问foo

foo = "test"

module GetVar
    def self.print_foo
        puts foo
    end
end

GetVar.print_foo

我可以通过将 foo 更改为常量 FOO 来使其工作,但这更像是一种 hack,我正在寻找更好的解决方案。我也不能,或者宁愿不让foo 成为实例变量@foo

【问题讨论】:

  • 您可以在模块中添加def self.foo; "test"; end
  • @CarySwoveland 不,这是因为我没有定义 foo - 实际上是“verify_recaptcha”,它来自另一个宝石。我正在使用 recaptcha gem,我正在尝试创建一个调用 verify_recaptcha 的辅助方法,但是辅助函数创建了一个新范围,它没有我需要从 recaptcha gem 获得的功能。
  • @ChristianJuth 局部变量对于当前对方法的调用是本地的,或者如果您在顶级绑定中定义,则对于顶级绑定是本地的。它不能也不应该在其他任何地方访问。
  • @ChristianJuth 你的问题听起来像是一个设计问题,所以你能问另一个关于你真正问题的问题吗?
  • @ChristianJuth :从技术上讲,您可以将 foo 设为全局变量 ($foo),但除非您有充分的理由这样做,否则不要这样做。正如 Aetherus 所说,这对我来说更像是一个设计问题。

标签: ruby scope


【解决方案1】:

简单的回答是:不,没有办法从print_foo方法的方法范围访问脚本范围内的局部变量foofoo 是一个局部变量,局部变量在它们定义的范围内是局部的,这就是为什么它们被称为“局部”变量,毕竟。

foo 在脚本范围内定义。没有定义在print_foo的方法范围内,所以不能从print_foo访问。

Ruby 中有四种局部变量作用域:脚本、模块/类定义、方法定义和 lambda 字面量/块体。在这四个中,脚本范围、模块/类范围和方法范围创建了新的范围。 Lambda 文字和块,只有这两个创建嵌套范围,可以从周围的词法范围访问局部变量。

因此,在print_foo 中访问foo 的唯一方法是确保print_foo 定义在嵌套范围内,即在一个块中,并且所有周围的范围也是块。值得庆幸的是,有一种方法可以定义名为 Module#define_method(或者在这种情况下实际上是 Object#define_singleton_method)的方法,它需要一个块,还有一种方法可以定义一个名为 Module::new 的模块,它也需要一个块:

有没有办法从GetVar.print_foo访问foo

foo = "test"

GetVar = Module.new do 
  define_singleton_method(:print_foo) do puts foo end
end

GetVar.print_foo
# test

实际上,我们甚至不需要Module::new的块形式:

foo = "test"

GetVar = Module.new.tap do |m| m.define_singleton_method(:print_foo) do puts foo end end

GetVar.print_foo
# test

【讨论】:

    【解决方案2】:

    使用class_eval

    class A
      @foo = "test"
    end
    module GetVar
      def self.print_foo
          A.class_eval do
            puts @foo
          end
      end
    end
    GetVar.print_foo
    #=> "test"
    

    或展平范围

    foo = "test"
    GetVar = Module.new do
      # define a class method
      define_singleton_method :print_foo do
        puts foo
      end
    end
    GetVar.print_foo
    #=> "test"
    

    看到这个问题:How to understand the difference between class_eval() and instance_eval()?

    【讨论】:

      猜你喜欢
      • 2020-07-30
      • 2012-12-10
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      相关资源
      最近更新 更多