内核#__ method__似乎在动态定义的方法中无法正常工作

我一直在尝试动态定义Ruby 1.9中的一些实例方法。 这是我用来尝试这个的代码:

class Testing [:one, :two].each do |name| define_method(name) do puts __method__ end end end 

这是输出:

 ruby-1.9.2-p180 :008 > t = Testing.new => # ruby-1.9.2-p180 :009 > t.one two => nil ruby-1.9.2-p180 :010 > t.two two => nil ruby-1.9.2-p180 :011 > 

我希望结果分别是onetwo 。 如果我在迭代之外调用每个的define_method它按预期工作。 我在这里不理解什么?

以下是我在网上看到的在迭代中调用define_method的众多示例之一。 使用define_method动态定义的setter方法?

少了什么东西?

另外:使用__method__对我来说并不重要,但这是我展示的最佳方式,似乎只有发送到define_method的最后一个块被用于定义的方法。 也许这开始向我解释问题,但我仍然不明白..

很好的发现奇怪的行为。 在我测试的所有ruby中,只有MRI 1.9.2certificate了这一点。

Ryan Davis 报告了ruby核心列表中的错误 (引用了这个问题)。

你可以使用这样的东西而不是define_method

 class Testing [:one, :two].each do |name| eval <<-EOM def #{name} puts __method__ end EOM end end t = Testing.new t.one #=> "one" t.two #=> "two" 

发生这种情况的原因是define_method以与def相比稍微不同的方式定义方法。 它与创建匿名触发器和lambdas有关。 我建议只使用方法名称,因为你已经拥有它。 这应该避免必须在堆栈跟踪中搜索方法名称,因此它应该执行得更好:

 class Testing [:one, :two].each do |name| define_method name do "This method's name is #{name}." end end end Testing.new.one => This method's name is one. Testing.new.two => This method's name is two. 

为了澄清,请注意以下两个语句返回的内容:

 class Testing define_method :one do __method__ end end => # class Testing def one __method__ end end => nil 

PS:使用这两种格式之间也存在性能差异。 您可以使用Benchmarkvalidation自己def比define_method更快。