在 define_method 中使用局部变量
Using local variables in define_method
我想了解 define_method
的工作原理以及如何正确使用定义块之外的变量。这是我的代码:
class Test
def self.plugin
for i in 1..2
define_method("test#{i}".to_sym) do
p i
end
end
end
plugin
end
ob = Test.new
ob.test1 #=> 2 (I would expect 1)
ob.test2 #=> 2 (I would expect 2)
好像在test1
和test2
方法中,i
的值在定义的时候没有代入,而是在方法调用的时候直接当场计算的.所以我们只看到 i
的最新值,即 2
。但是 Ruby 从哪里获取这个值呢?有没有办法让test#{i}
打印i
?
在这种特殊情况下,我可以做 workaround using __method__
,但可能有更好的解决方案。
正如评论中提到的那样,这取决于闭包——传递给 define_method
的块从其作用域中捕获局部变量(而不仅仅是您发现的它们的值)。
for
不会创建新范围,因此您的方法 'sees' 更改为 i
。如果您使用一个块(例如每个块),则会创建一个新范围,这不会发生。您只需要将代码更改为
class Test
def self.plugin
(1..2).each do |i|
define_method("test#{i}".to_sym) do
p i
end
end
end
plugin
end
这基本上就是 Arup 链接的问题
我想了解 define_method
的工作原理以及如何正确使用定义块之外的变量。这是我的代码:
class Test
def self.plugin
for i in 1..2
define_method("test#{i}".to_sym) do
p i
end
end
end
plugin
end
ob = Test.new
ob.test1 #=> 2 (I would expect 1)
ob.test2 #=> 2 (I would expect 2)
好像在test1
和test2
方法中,i
的值在定义的时候没有代入,而是在方法调用的时候直接当场计算的.所以我们只看到 i
的最新值,即 2
。但是 Ruby 从哪里获取这个值呢?有没有办法让test#{i}
打印i
?
在这种特殊情况下,我可以做 workaround using __method__
,但可能有更好的解决方案。
正如评论中提到的那样,这取决于闭包——传递给 define_method
的块从其作用域中捕获局部变量(而不仅仅是您发现的它们的值)。
for
不会创建新范围,因此您的方法 'sees' 更改为 i
。如果您使用一个块(例如每个块),则会创建一个新范围,这不会发生。您只需要将代码更改为
class Test
def self.plugin
(1..2).each do |i|
define_method("test#{i}".to_sym) do
p i
end
end
end
plugin
end
这基本上就是 Arup 链接的问题