在 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)

好像在test1test2方法中,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 链接的问题