方法是在没有调用的情况下执行的?

Method is executed without calling it?

我在 the Ruby koans 中遇到了代理 class 的这个解决方案:

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

我可以通过传递另一个 class 作为参数从这个代理 class 创建一个对象。例如,以下代码将生成 "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 中的代码无需调用上述方法就可以执行?

当某个事件发生或某个方法被调用时,有些方法会被隐式调用(即,即使您没有在代码中编写它也会被调用)。我将这些方法称为 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 是最默认的方法,它被调用的优先级最低。

method_missing 是 ruby 中 metaprogramming 的惊人方面之一。通过正确使用此方法,您可以优雅地处理异常等等。在你的情况下,它被调用是因为你在对象上调用的方法显然不存在。

但也要注意使用。当你在看它的时候,也要看看 responds_to 方法。

有关 ActiveRecord 的示例将使您更好地理解。当我们写:

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

实际上并没有同名的方法。此调用转到 method_missing,然后这个花哨的 find 方法被分解成多个部分,并为您提供所需的服务。希望对您有所帮助。