Ruby:define_method与def

作为编程练习,我编写了一个创build类的Ruby片段,实例化该类中的两个对象,monkeypatches一个对象,并依靠method_missing来monkeatch另一个对象。

这是交易。 这按预期工作:

class Monkey def chatter puts "I am a chattering monkey!" end def method_missing(m) puts "No #{m}, so I'll make one..." def screech puts "This is the new screech." end end end m1 = Monkey.new m2 = Monkey.new m1.chatter m2.chatter def m1.screech puts "Aaaaaargh!" end m1.screech m2.screech m2.screech m1.screech m2.screech 

你会注意到我有一个method_missing的参数。 我这样做是因为我希望使用define_methoddynamic创build具有适当名称的缺less方法。 但是,它不起作用。 实际上,即使使用如下静态名称的define_method:

 def method_missing(m) puts "No #{m}, so I'll make one..." define_method(:screech) do puts "This is the new screech." end end 

结束以下结果:

 ArgumentError: wrong number of arguments (2 for 1) method method_missing in untitled document at line 9 method method_missing in untitled document at line 9 at top level in untitled document at line 26 Program exited. 

是什么让错误信息更令人困惑的是,我只有一个method_missing参数…

define_method是对象Class的(私有)方法。 你正在从一个实例调用它。 没有实例方法叫做define_method ,所以它recursion到你的method_missing ,这次是:define_method (缺less方法的名字)和:screech (你传递给define_method的唯一参数)。

试试这个(在所有的猴子对象上定义新的方法):

 def method_missing(m) puts "No #{m}, so I'll make one..." self.class.send(:define_method, :screech) do puts "This is the new screech." end end 

或者这个(只在被调用的对象上使用对象的“本征类”来定义它):

 def method_missing(m) puts "No #{m}, so I'll make one..." class << self define_method(:screech) do puts "This is the new screech." end end end 

self.class.define_method(:screech)不起作用,因为define_method是私有方法,你可以这样做

 class << self public :define_method end def method_missing(m) puts "No #{m}, so I'll make one..." Monkey.define_method(:screech) do puts "This is the new screech." end 
 def method_missing(m) self.class.class_exec do define_method(:screech) {puts "This is the new screech."} end end 

所有的猴子对象都有可用的尖叫方法。