読者です 読者をやめる 読者になる 読者になる

【Ruby】メソッド一覧とMethodオブジェクトの取得

スポンサーリンク

クラスに定義されているメソッドの確認と、Method や UnboundMethod オブジェクトを取得する方法です。

メソッドの一覧

メソッド 機能
Object#methods public と protected メソッド名の一覧
Object#singleton_methods 特異メソッド名の一覧
Object#public_methods public メソッド名の一覧
Object#protected_methods protected メソッド名の一覧
Object#private_methods private メソッド名の一覧

次のクラスを使用して各メソッドの一覧を取得してみます。

class Hello
  def self.singleton_hello; end

  public
  def public_hello; end

  protected
  def protected_hello; end

  private
  def private_hello; end
end

Hello クラスのメソッド一覧を取得するには以下の方法があります。メソッド名が大量に出力される場合もあるので引数に false を渡しています。

Hello.methods(false)
=> [:singleton_method]
Hello.singleton_methods(false)
=> [:singleton_method]
Hello.public_methods(false)
=> [:singleton_method, :new, :allocate, :superclass]  # public_helloメソッドはクラスオブジェクトからは参照できない
Hello.protected_methods(false)
=> []  # protected_helloメソッドはクラスオブジェクトからは参照できない
Hello.private_methods(false)
=> [:initialize, :inherited]  # private_helloメソッドはクラスオブジェクトからは参照できない

hello = Hello.new
hello.methods(false)
=> []  # 特異メソッドはインスタンスオブジェクトからは参照できない
hello.singleton_methods(false)
=> []  # 特異メソッドはインスタンスオブジェクトからは参照できない
hello.public_methods(false)
=> [:public_hello]
hello.protected_methods(false)
=> [:protected_hello]
hello.private_methods(false)
=> [:private_hello]

モジュールで定義されているインスタンスメソッドの一覧を返します。

メソッド 機能
Module#instance_methods public と protected メソッド名の一覧
Module#public_instance_methods public メソッド名の一覧
Module#protected_instance_methods protected メソッド名の一覧
Module#private_instance_methods private メソッド名の一覧
Hello.instance_methods(false)
=> [:public_hello, :protected_hello]
Hello.singleton_instance_methods(false)
NoMethodError: undefined method singleton_instance_methods for Hello:Class
from (pry):4:in <main>  # 特異メソッドはインスタンスメソッドではないため
Hello.public_instance_methods(false)
=> [:public_hello]
Hello.protected_instance_methods(false)
=> [:protected_hello]
Hello.private_instance_methods(false)
=> [:private_hello]

このメソッドはインスタンス化したオブジェクトからは呼び出せません。

hello.private_instance_methods(false)  #=> NoMethodError: undefined method `private_instance_methods' for #<Hello:0x007f9de98fc418>
hello.class.private_instance_methods(false)
=> [:private_hello]

Methodオブジェクトの取得

様々な方法でメソッド一覧が取得できることがわかりました。そしてメソッド一覧を取得するメソッド名から末尾のsを消して引数にメソッド名を渡すと Method オブジェクトを取得することができます。ただし全てにs無しのメソッドが定義されているわけではありません。

メソッド 機能
Object#method オブジェクトのメソッドをオブジェクト化した Method を返す。
Object#singleton_method オブジェクトの特異メソッドをオブジェクト化した Method を返す。
Object#public_method オブジェクトの public メソッドをオブジェクト化した Method を返す。
Module#instance_method インスタンスメソッドの UnboundMethod を返す。
Module#public_instance_method public インスタンスメソッドの UnboundMethod を返す。

特異メソッドと public メソッドの取得方法です。

Hello.method(:singleton_hello)
=> #<Method: Hello.singleton_hello>
Hello.method(:public_hello)
=> #<Method: Class(Kernel)#public_hello>
Hello.singleton_method(:singleton_hello)
=> #<Method: Hello.singleton_hello>
Hello.public_method(:singleton_hello)
=> #<Method: Hello.singleton_hello>
hello.public_method(:public_hello)
=> #<Method: Hello#public_hello>
Hello.instance_method(:public_hello)
=> #<UnboundMethod: Hello#public_hello>
Hello.public_instance_method(:public_hello)
=> #<UnboundMethod: Hello#public_hello>

protected と private メソッドに関してはクラスオブジェクトに対するinstance_methodかインスタンスに対するmethodで取得できます。

Hello.instance_method(:private_hello)
=> #<UnboundMethod: Hello#private_hello>
Hello.instance_method(:protected_hello)
=> #<UnboundMethod: Hello#protected_hello>
hello.method(:protected_hello)
=> #<Method: Hello#protected_hello>
hello.method(:private_hello)
=> #<Method: Hello#private_hello>