我编写的“编程Ruby”中的method_missing

时间:2009-04-03 20:01:15

标签: ruby method-missing

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编写代码)?

7 个答案:

答案 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