Ruby においてメソッドがどこで定義されているのかを調べる方法

ruby-talk の 381425 で 「どのメソッドが呼び出されているのか調べる方法を知りたい」 という内容の質問がありました。 私も知らなかったのですが、Method オブジェクトを使えば簡単に知ることができるそうです。

というわけで、メソッドがどこで定義されているのかを調べる方法を書いておきます。

メソッドを定義しているクラスまたはモジュールへの参照を取得する

あるメソッドがどのクラス (またはモジュール) で定義されているかを知りたければ、そのメソッドに対応する Method オブジェクトを取得し、Method#owner メソッド を呼び出します。 それだけで、メソッドを定義しているクラス (またはモジュール) への参照を取得できます。

ちなみに、ある名前のメソッドに対応する Method オブジェクトを取得するには、Kernel#method メソッド を使用します。

'あい'.method( :to_s )
  #=> #<Method: String#to_s>
  # String オブジェクトの to_s メソッドに対応する Method オブジェクトを取得

以下に、指定したメソッドを定義しているクラスまたはモジュールへの参照を取得する方法の例を示します。

# 例として用いる Test クラスを生成
class Test
  # インスタンスメソッド
  def do_i
  end
  # クラスメソッド
  def self.do_c
  end
end

# == Test クラスの do_c クラスメソッドがどこで定義されているか調べる ==
# Test クラスの do_c メソッドに対応する Method オブジェクトを取得
m = Test.method( :do_c )
  #=> #<Method: Test.do_c>
# Method#owner メソッドの呼び出し
m.owner
  #=> #<Class:Test>
  # Test クラスの do_c クラスメソッドは Test クラスオブジェクトの
  # 固有クラスで定義されていることがわかる

# == Test オブジェクトの do_i メソッドがどこで定義されているか調べる ==
# Test オブジェクトの do_i メソッドに対応する Method オブジェクトを取得
m = Test.new().method( :do_i )
  #=> #<Method: Test#do_i>
# Method#owner メソッドの呼び出し
m.owner
  #=> Test
  # Test オブジェクトの do_i メソッドは Test クラスで
  # 定義されていることが分かる

# == Test オブジェクトの to_s メソッドがどこで定義されているか調べる ==
# Test オブジェクトの to_s メソッドに対応する Method オブジェクトを取得
m = Test.new().method( :to_s )
  #=> #<Method: Test(Kernel)#to_s>
# Method#owner メソッドの呼び出し
m.owner
  #=> Kernel
  # Test オブジェクトの to_s メソッドは Kernel モジュールで
  # 定義されていることがわかる

Ruby 1.8.7 および Ruby 1.9.2 で動作することを確認しました。

どのファイルで定義されているのか?

Ruby 1.9.2 には Method#source_location メソッド があり、これを使えばどのファイルの何行目でメソッドが定義されているかを調べることができます。 (Ruby コードで書かれている場合。 ネイティブコードなどでは nil になります。) 残念ながら Ruby 1.8 にはないようです。