有没有办法判断是否明确调用了`method_missing`?

时间:2016-02-07 06:51:47

标签: ruby metaprogramming

从方法定义中,有没有办法判断方法method_missing是显式调用还是被称为钩子方法?

使用方法initialize,可以通过执行以下操作来判断它是显式调用还是被称为挂钩:

class A
  def initialize
    puts caller
  end
end

当被称为钩子时,方法initialize有一行new

a = A.new
# => ...:in `new'
# => ...
# => ...:in `<main>'

当显式调用时,它没有这样的行(除非它是从new明确调用的):

a.send(:initialize)
# => ...
# => ...:in `<main>'

但是当我对method_missing做类似的事情时,我无法区分这两种情况:

class A
  def method_missing *;
    puts caller
  end
end

a.foo
# => ...
# => ...:in `<main>'

a.method_missing
# => ...
# => ...:in `<main>'

2 个答案:

答案 0 :(得分:2)

您可以查看第一个参数:

class A
  def method_missing(name = nil, *)
    if name
      puts "called via `#{name}'"
    else
      puts "called directly"
    end
  end
end

A.new.foo
#=> called via `foo'

A.new.method_missing
#=> called directly

答案 1 :(得分:1)

initialize不同,is invoked explicitly via the Class#new,Ruby解释器调用BasicObject#method_missing

  

当obj被发送一条无法处理的消息时,由Ruby调用。符号是   调用方法的符号,args是任何参数   传递给它。默认情况下,解释器会在此时引发错误   方法被调用。但是,可以将方法覆盖为   提供更有活力的行为。

Kernel#caller不会在执行堆栈跟踪中包含那些位置,Ruby解释器会调用method_missing,如果这就是您要查找的内容。