当通过alias_method创建的方法调用时,__callee__将忽略旧方法的名称(这里为xxx),并返回新方法的名称,如下所示:
class Foo def xxx() __callee__ end alias_method :foo,:xxx end Foo.new.foo # => :foo
即使xxx从一个超类继承,这种行为也是一样的:
class Sup def xxx() __callee__ end end class Bar < Sup alias_method :bar,:xxx end Bar.new.bar # => :bar
考虑到上述两种情况,我希望当通过模块包含xxx时,同样的行为将成立.但是,情况并非如此:
module Mod def xxx() __callee__ end end class Baz include Mod alias_method :baz,:xxx end Baz.new.baz # => :xxx
我希望返回值为:baz,而不是:xxx.
上面的代码是使用Ruby 2.3.1p112执行的.这是执行__callee__的错误吗?或者可能是alias_method?如果没有,任何人都可以解释为什么模块包含行为不同?
更新1
我有posted this to the Ruby bug tracker尝试挑起一个答案.
更新2
显然,我是not the only one对这个问题感到惊讶.我想知道Revision 50728(这是为了解决Bug 11046: __callee__
returns incorrect method name in orphan proc)可能是相关的.
解决方法
您可以在Ruby的内核模块中看到__callee__和__method__之间的区别.
不同之处在于调用prev_frame_callee()和prev_frame_func().我在http://rxr.whitequark.org/mri/source/eval.c发现了这些功能定义
简而言之,Foo和Bar立即调用别名方法foo和bar(它们是xxx的名称),而Baz必须找到Mod并从Mod调用xxx. __method__查找原始调用方法的id,而__callee__查找__callee__调用中最近调用的方法的id.在第848到906行的eval.c中更好地看到:在类似于< something>的返回调用上查找两个方法的区别. – > called_id对< something> – > def-> original_id.
另外,如果从1.9.3版本看内核,你会发现这两个方法最初是一样的.所以,在某些时候,两者之间有一个有意义的变化.