method_missing
* obj.method_missing(符号h, args i)→other_obj
当发送obj时由Ruby调用 它无法处理的消息。符号是 调用方法的符号,和 args是任何参数 传递给它。以下示例 创建一个响应的罗马类 到名称由...组成的方法 罗马数字,归还 相应的整数值。更多 method_missing的典型用法是 实现代理,委托和 转发器。
class Roman
def roman_to_int(str)
# ...
end
def method_missing(method_id)
str = method_id.id2name
roman_to_int(str)
end
end
r = Roman.new
r.iv ! 4
r.xxiii ! 23
r.mm ! 2000
我刚刚听说缺少方法,并在 Programming Ruby 中找到了更多信息,但本书引用的上述解释已经超出了我的想法。有没有人有更简单的解释?更具体地说,方法缺失只是由解释器使用,或者是否需要直接在程序中调用它(假设我只是编写Web应用程序,而不是为NASA编写代码)?
答案 0 :(得分:12)
最好不要将红宝石视为有方法。当您调用ruby“方法”时,您实际上是向该实例(或类)发送消息,如果您已为该消息定义了处理程序,则它将用于处理并返回值。
所以method_missing
是一个特殊的定义,只要ruby找不到合适的处理程序就会调用它。您也可以将其视为*
方法。
答案 1 :(得分:5)
对于与任何方法都不匹配的消息,它基本上是一个全能。它广泛用于动态查找器的活动记录中。这就是让你写下这样的东西:
SomeModel.find_by_name_and_number(a_name, a_number)
模型不包含该find_by的代码,因此调用method_missing时会看到 - 我识别该格式并执行它。如果没有,那么你会得到一个找不到方法的错误。
答案 2 :(得分:5)
Ruby没有任何类型强制执行,同样也没有检查对象在首次解析脚本时的方法,因为这可以在应用程序运行时动态更改。
method_missing的作用是拦截和处理对给定对象不存在的方法的调用。这为几乎所有用Ruby编写的DSL(特定于域的语言)提供了引擎盖下的功能。
在示例的情况下,'r.iv','r.mm'等中的每一个实际上都是对Roman对象的方法调用。当然,它没有'iv'或'mm'方法,所以将控制传递给method_missing,它获取被调用方法的名称,以及传递的参数。
method_missing然后将方法名称从符号转换为字符串,并将其解析为罗马数字,并将输出作为整数返回。
答案 3 :(得分:3)
在您提供的罗马示例中,它说明了如何在不明确定义方法的情况下扩展类的功能。
r.iv不是一种方法,因此method_missing
会抓住它并在方法ID“iv”上调用roman_to_int
当你想在其他地方处理无法识别的方法时,它们也很有用,比如代理,委托和转发器,如文档所述。
答案 4 :(得分:2)
您不会调用“method_missing
”(解释程序会调用它)。相反,你定义它(覆盖它)为你想要更灵活的类。正如其他注释中所提到的,当类(或实例)没有(“显式”?)定义所请求的方法时,解释器将调用您的method_missing
版本。这使您有机会根据ersatz方法/消息名称进行操作。
您是否曾在Java中进行过任何“反射”编程?使用这种方法就好像通过反射访问的类可以查看方法名称的字符串(对不起,“符号”),如果抛出了一个没有这样的方法异常,然后按照该方法创建一些东西即时实施。
动态编程在反思中是一种“一对一”。
答案 5 :(得分:1)
既然你提到了网络应用,我猜你会熟悉Ruby on Rails。可以使用method_missing
的一个很好的例子是可用的不同find_by_<whatever>
方法。这些方法都不存在!它们在运行期间合成。所有这些魔法的发生都是因为ruby拦截了对不存在的方法的调用。
您可以详细了解method_missing here的用法和其他用法。
答案 6 :(得分:1)
ActiveRecord使用method_missing
来定义find_by方法。但是,因为method_missing
基本上是最后的手段,这可能是一个严重的性能瓶颈。我发现ActiveRecord通过将新的finder方法定义为类方法来做一些更棒的元编程!因此,对同一个finder方法的任何进一步调用都不会命中method_missing
,因为它现在是一个类方法。有关base.rb中实际代码段的详细信息,请单击here。