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
所有的猴子对象都有可用的尖叫方法。