作为一个编程练习,我编写了一个Ruby片段,它创建了一个类,从该类中实例化了两个对象,monkeypatches一个对象,并依赖于method_missing来monkeypatch另一个.
这是交易.这按预期工作:
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_method动态创建具有适当名称的缺失方法.但是,它不起作用.实际上,即使使用带有静态名称的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
,因此它会method_missing
使用:define_method
(缺少方法的名称)和:screech
(传递给的唯一参数)递归到您的define_method
.
试试这个(在所有Monkey对象上定义新方法):
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