2

我在 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 实例, hitmethod_missing和瞧。为什么method_missing在使用直接调用__send__时我没有调用?

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

4

2 回答 2

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__尝试在继承链中调用从 Kernel 继承的私有方法,因此不使用__send__使用 Ruby 的public_send方法。

于 2013-07-11T20:28:29.110 回答
1

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

[Testerize, Object, Kernel, BasicObject]

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

于 2013-07-11T20:09:29.340 回答