在ruby中,编译器并不强制方法调用时的行为,这意味着你可以调用一个并不存在的方法。例如:

class Lawyer;end
nick = Lawyer.new
nick.talk_simple

NoMethodError: undefined method ‘talk_simple’ ……

当调用talk_simple()方法时,ruby会到nick对象的类中查询它的实例方法,如果找不到,ruby会沿着祖先链向上搜寻进入Object类,并最终来到Kernel模块。

由于ruby没有找到talk_simple()方法,ruby只好承认自己失败了,并在nick对象(最初的接收者)上调用一个名为method_missing()的方法。

ruby知道总会存在一个method_missing()方法,因为它是Kernel的一个实例方法, 所有的对象都继承自Kernel模块。

我们可以通过覆写method_missing()方法来截获无主的消息,因为每一个调用method_missing()方法的消息都带着被调用方法的名字,以及所有调用时传递的参数和块。

 下面看一个模拟OpenStruct的例子:

class MyOpenStruct
         def initialize
                   @attributes  = {}
         end
         def method_missing(name, *args)
                   attribute = name.to_s
                   if attribute =~ /=$/
                            @attributes[attribute.chop] = args[0]
                   else
                            @attributes[attribute]
                   end
         end
end

icecream = MyOpenStruct.new
icecream.flavor = “vanilla”
icecream.flavor   #=> “vanilla”

MyOpenStruct#method_missing()方法会捕捉 flavor=() 方法的调用,再砍掉最后的那个 “=”以获得属性的名字,然后它把属性名和对应的值放入一个哈希表中,当调用一个不已“=”结尾的方法时,method_missing() 方法会在哈希表中查找相应的方法名,并返回对应的值。