在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() 方法会在哈希表中查找相应的方法名,并返回对应的值。