在define_method中使用局部变量

时间:2015-05-30 10:30:00

标签: ruby metaprogramming

我想了解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)

似乎在方法test1test2中,i的值在定义期间未被替换,而是在调用方法时直接在现场计算。因此,我们只看到i的最新值,即2。但Ruby从哪里获取此值?有没有办法让test#{i}打印i

在这种特殊情况下,我可以做workaround using __method__,但可能有更好的解决方案。

1 个答案:

答案 0 :(得分:6)

正如在评论中提到的,这取决于闭包 - 传递给define_method的块从其范围捕获局部变量(而不仅仅是你发现的值)。

for没有创建新的范围,因此您的方法会看到'对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所关联的问题是关于