简体   繁体   English

Ruby模块无法访问局部变量

[英]Ruby Module can't access local variable

Is there anyway to access foo from GetVar.print_foo ? 无论如何,可以从GetVar.print_foo访问foo吗?

foo = "test"

module GetVar
    def self.print_foo
        puts foo
    end
end

GetVar.print_foo

I was able to get it to work by changing foo to a constant FOO , but this is more of a hack and I am looking for a better solution. 我可以通过将foo更改为一个恒定的FOO使其工作,但这更多的是hack,我正在寻找更好的解决方案。 I also can't, or rather prefer not, to make foo an instance variable @foo . 我也不能,或者宁愿不喜欢,也不能使foo成为实例变量@foo

The simple answer is: no, there is no way to access the local variable foo in the script scope from the method scope of the print_foo method. 简单的答案是:不,没有办法从print_foo方法的方法范围访问脚本范围中的局部变量foo foo is a local variable, local variables are local to the scope they are defined in, that's why they are called "local" variables, after all. foo是一个局部变量,局部变量在定义它们的作用域内是局部的,这就是为什么它们被称为“局部”变量的原因。

foo is defined in the script scope. foo在脚本作用域中定义。 It is not defined in the method scope of print_foo , ergo, it cannot be accessed from print_foo . 它在ergo的print_foo的方法范围内print_foo ,因此无法从print_foo进行访问。

There are four local variable scopes in Ruby: script, module / class definition, method definition, and lambda literal / block body. 在Ruby中有四个局部变量作用域:脚本,模块/类定义,方法定义和lambda文字/块体。 Of these four, script scope, module / class scope, and method scope create new scopes. 在这四个脚本范围,模块/类范围和方法范围中,创建了新的范围。 Lambda literals and blocks, and only those two create nested scopes that can access local variables from their surrounding lexical scopes. Lambda文字和块, 只有这两个会创建嵌套的作用域,可以从其周围的词法作用域访问局部变量。

So, the only way to get access to foo in print_foo is to make sure that print_foo is defined in a nested scope, ie in a block, and that all the surrounding scopes are also blocks. 因此,在print_foo访问foo的唯一方法是确保在嵌套作用域(即块中)中定义了print_foo ,并且所有周围的作用域也是块。 Thankfully, there is a method for defining methods called Module#define_method (or in this case actually Object#define_singleton_method ) that takes a block, and there is a method for defining a module called Module::new that also takes a block: 值得庆幸的是,有一个方法定义了一个名为Module#define_method (或者在本例中为Object#define_singleton_method ),该方法带有一个块,还有一个用于定义名为Module::new的模块的方法,该方法也带有一个块:

Is there anyway to access foo from GetVar.print_foo ? 无论如何,可以从GetVar.print_foo访问foo吗?

foo = "test"

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

GetVar.print_foo
# test

Actually, we don't even need the block form of Module::new : 实际上,我们甚至不需要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

Use class_eval 使用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"

or flattening the scope 或展平范围

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

See this question: How to understand the difference between class_eval() and instance_eval()? 看到这个问题: 如何理解class_eval()和instance_eval()之间的区别?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM