方法执行而不调用它?

时间:2015-12-14 01:41:30

标签: ruby method-call

我在the Ruby koans中找到了针对代理类的解决方案:

class Proxy
  attr_accessor :messages

  def initialize(target_object)
    @object = target_object
    @messages = []
  end
  def method_missing(method_name, *args, &block)
    @messages << method_name
    @object.send(method_name, *args, &block)
  end
end

我可以通过传递另一个类作为参数来从这个代理类创建一个对象。例如,以下代码将生成"Do something",而无需键入thing.method_missing(:do_thing)

class Thing
  def do_thing
    puts "Doing something."
  end
end

thing = Proxy.new(Thing.new)
thing.do_thing

为什么method_missing中的代码无需调用所述方法即可执行?

2 个答案:

答案 0 :(得分:4)

当某个事件发生或某个方法被调用时,有些方法被隐式调用(即,即使你没有在代码中写入它也会被调用)。我将这些方法称为 hooks ,借用e-lisp的术语。据我所知,Ruby有以下钩子:

Ruby挂钩

at_exit
set_trace_func
initialize
method_missing
singleton_method_added
singleton_method_removed
singleton_method_undefined
respond_to_missing?
extended
included
method_added
method_removed
method_undefined
const_missing
inherited
initialize_copy
initialize_clone
initialize_dup
prepend
append_features
extend_features
prepend_features

method_missing就是其中之一。对于这个特定的,当Ruby找不到定义的方法时会自动调用它。或者换句话说,对于任何方法调用,method_missing是使用最低优先级调用的最默认方法。

答案 1 :(得分:1)

method_missing是红宝石中metaprogramming的惊人方面之一。正确使用此方法,您可以优雅地处理异常和诸如此类的东西。在你的情况下,它被调用,因为你在对象上调用的方法显然不存在。

但是人们也应该小心使用它。在你做的时候,也要看responds_to方法。

关于ActiveRecord的示例会让您更好地理解。当我们写:

User.find_by_email_and_age('me@example.com', 20)

实际上没有一个名称的方法。此调用转到method_missing,然后将这种花哨的find方法分解为多个部分,并按照您的要求提供服务。我希望有所帮助。