元编程:method_missing和__send__

时间:2013-07-11 20:00:43

标签: ruby metaprogramming method-missing

我发现Ruby很奇怪。当内核定义相同的方法时,使用method_missing / respond_to_missing?动态处理通过__send__启动的方法调用失败:

class Testerize

  def method_missing(method, *args, &block)
    if method == :system
      puts 'yay'
    else
      super
    end
  end

  def respond_to_missing?(method, internal)
    return true if method == :system
  end

end

t = Testerize.new
puts t.respond_to?(:system)
# Prints true
t.system
# Prints 'yay'
t.__send__(:system)
# Exception: wrong number of arguments (ArgumentError)

Kernel.system以某种方式进入组合。有谁知道这里发生了什么?我本来期望:system“消息”发布到Testerize实例,点击method_missing,然后瞧。当 直接调用时,为什么method_missing在使用__send__时被调用?

我正在使用Ruby 1.9.3,如果这是相关的。

2 个答案:

答案 0 :(得分:3)

with '__send__' or 'send' we can even call private methods of the object.

在你的脚本中执行:

t.private_methods.grep /system/

您将看到system方法,而

t.methods.grep /system/

你会看到一个空数组。

__send__尝试在继承链中调用从内核继承的私有方法,因此不使用__send__使用Ruby的public_send方法。

答案 1 :(得分:1)

如果你查找班级的祖先链(Testerize.ancestors),你会发现:

[Testerize, Object, Kernel, BasicObject]

由于新类默认继承自ObjectObject继承自Kernel,因此Kernel可用的所有实例方法都可用于您的实例。