是否可以从foo
访问GetVar.print_foo
?
foo = "test"
module GetVar
def self.print_foo
puts foo
end
end
GetVar.print_foo
我可以通过将foo
更改为常量FOO
来使其工作,但这更像是一个黑客,我正在寻找更好的解决方案。我也不能,或者更不愿意,将foo
变为实例变量@foo
。
答案 0 :(得分:1)
简单的答案是:不,没有办法从foo
方法的方法范围访问脚本范围中的局部变量print_foo
。 foo
是一个局部变量,局部变量是它们定义的范围的局部变量,这就是为什么它们被称为" local"毕竟是变量。
foo
在脚本范围中定义。它没有在print_foo
的方法范围中定义,因此无法从print_foo
访问它。
Ruby中有四个局部变量作用域:脚本,模块/类定义,方法定义和lambda文字/块体。在这四个中,脚本范围,模块/类范围和方法范围创建新范围。 Lambda文字和块,以及仅这两个创建嵌套范围,可以从其周围的词法范围访问局部变量。
因此,在foo
中访问print_foo
的唯一方法是确保print_foo
在嵌套范围内定义,即在块中定义,以及所有周围环境范围也是块。值得庆幸的是,有一种方法可以定义一个名为Module#define_method
的方法(或者在这种情况下实际上是Object#define_singleton_method
),它采用一个块,并且有一种方法可以定义一个名为Module::new
的模块。一个街区:
是否可以从foo
访问GetVar.print_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
答案 1 :(得分:0)
使用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()?