14

によって作成されたメソッドを介して呼び出された場合、 は古いメソッドの名前 (ここでは )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

これをRubyバグトラッカーに投稿して、答えをかき立てようとしました。


更新 2

どうやら、この問題に驚いたのは私だけではないようです。リビジョン 50728 (バグ 11046:__callee__孤立した proc で不正なメソッド名を返す) を解決するためのものでした) が関連しているのではないかと思います。

4

2 に答える 2

2

と の違いは、Ruby の Kernel モジュールで確認でき__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__探し、呼び出しに最も近い呼び出されたメソッドの IDを探し__callee__ます。これは 848 ~ 906 行でよくわかります。 vseval.cと同様に、リターン コールで 2 つのメソッドの違いを探します。<something> -> called_id<something> -> def->original_id

また、バージョン 1.9.3 からのカーネルを見ると、2 つのメソッドが元々同じであったことがわかります。そのため、ある時点で、両者の間に意図的な変更がありました。

于 2016-05-19T12:57:04.090 に答える