tl;dr;
基本的には以下のページで説明されているとおりだと思います。
この記事は、これらを少し長めのコードで試してみたものです。
関数オブジェクトを取得
Object#methodで取得できるとのことで、まずは試してみました。
以下のことが分かりました。
- トップレベルでのメソッド定義はmodule Kernelにプライベートメソッドとして追加される
- トップレベルのselfであるmainで呼べるようになる
- method(:hello) (つまり self.method(:hello) で)トップレベルの hello をオブジェクトとして取得できる
- 定義したクラスのメソッドも instance.method(:hello) で取得できる
レシーバの確認
Object#methodから返ってくるのはclass Methodのオブジェクトで、「メソッドの実体(名前でなく)とレシーバの組を封入します」とのことなので、どのような意味か確認しました。
Object#methodを呼んだ際のレシーバが、暗黙のレシーバであるselfとして封入されていそうです。
Procはどうなっているか?
暗黙のレシーバの確認をしていて、そういえばProcだどどうなんだろうと思って調べてみました。
Procは「ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです」とのことなので、selfへの参照も含まれるということだと思います。
class UnboundMethodの存在
ここまで忘れていましたが、Module#instance_methodを使うと、レシーバをもたないオブジェクトを取得することができるようです。
Module#instance_method に「バインドできるのは、 生成元のクラスかそのサブクラスのインスタンスのみです。」とあるとおり、確かにサブクラスでもないObjectをbindしようとしたらTypeErrorになりました。
まとめ
- Object#methodで関数オブジェクトを取得できる
- 関数オブジェクト(MethodやProc)はレシーバの情報ももっていて、オブジェクトをcallした場合にはそれが暗黙のレシーバとして使われる
- レシーバをもたないclass UnboundMethodもあるが、UnboundMethod#bindしないと呼べない
ということのようです。