有没有一种方法可以知道调用的方法?

6
我知道class方法可以告诉我们一个对象所属的类名,那么如何知道调用该方法的方法名呢?有没有办法知道这个呢?

4
这并不是一个无效的问题,但通常需要查看调用堆栈意味着你正在做一些错误的事情。 - R. Martinho Fernandes
4个回答

10

检查Ruby调用堆栈分享了这些信息:

你是否曾经想要在不引发异常的情况下查看调用堆栈?

caller.each {|c| puts c}

3

Caller是一个内核方法,可以让你做到这一点,因此caller[0]将让你知道函数的直接调用者。

获取函数名称的快速方法可能是一个简单的hack:

caller[0][/`\S+/].chop[1..-1]

这将以字符串形式返回调用方法的名称,您可以随意使用它。


1

Ruby的Kernel#caller实现是使用String来提高性能和垃圾回收效率。如果您想进行更复杂的调用堆栈分析,请参考这篇博客文章:

http://eigenclass.org/hiki/ruby+backtrace+data

作者讲解了两种不同的改进调用栈对象图的实现方式,一种是在纯Ruby中使用(不太常见的)Kernel#set_trace_func方法实现,另一种则作为C扩展程序运行于MRI中。
生产环境下的应用程序不应使用除Ruby自带的Kernel#caller实现之外的任何东西。如果您广泛使用上述扩展程序,可能会导致Ruby无法有效进行垃圾回收并拖慢进程速度(我估计)高达数个数量级。

0
你可以写出类似这样的代码:
module Kernel
  private
  def who_is_calling? # Or maybe def who_just_called?
    caller[1] =~ /`([^']*)'/ and $1
  end
end

然后你有这些小测试:

irb(main):056:0*   def this_is_a_method
irb(main):057:1>     puts "I, 'this_is_a_method', was called upon by: '#{who_is_calling?}'"
irb(main):058:1>   end
=> nil
irb(main):059:0>   def this_is_a_method_that_calls_another
irb(main):060:1>     this_is_a_method
irb(main):061:1>   end
=> nil
irb(main):062:0> this_is_a_method_that_calls_another
I, 'this_is_a_method', was called upon by: 'this_is_a_method_that_calls_another'
=> nil
irb(main):063:0> this_is_a_method
I, 'this_is_a_method', was called upon by: 'irb_binding'
=> nil
irb(main):064:0>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接