リフレクションとは、プログラムの(実行前ではなく)実行時にプログラムそのものの情報を参照・書き換えることができる特性を指します。

In computer science, reflection is the ability of a computer program to examine (see type introspection) and modify the structure and behavior (specifically the values, meta-data, properties and functions) of the program at runtime.

Reflection (computer programming) - Wikipedia, the free encyclopedia

Rubyは豊富なリフレクション機能を持っています。今回の記事では関連メソッドを簡単に紹介して行きたいと思います。

eval

特に中心となるメソッドとして、evalが挙げられます。evalは"evaluate(評価する)"から名付けられた、文字列を引数として取り、文字列の内容をRubyコードとして実行するメソッドです。

ふたつめの例ではヒアドキュメントで文字列をevalに渡し、文字列の内容を#{...}による埋め込みで書き換えつつ繰り返すことで、冗長なメソッド定義のコード量を抑えています。

ちなみにメソッド定義に限れば、 evalを使わずともdefine_method という専用のメソッドもあります。

コンテキストとself

以下で「コンテキスト」という言葉を使っていきますが、これは「そのコードが"どこ"で実行されたものとみなすか」を指します。具体的には「XのコンテキストでコードCを評価する」とは

  • コードC内のselfがXになる
  • コードC内から参照可能な変数セット(環境)がXと同じになる

という意味を持ちます。

eval族

evalは呼び出された箇所のコンテキストで文字列をRubyコードとして評価しますが、instance_evalclass_evalmodule_evalを使うと、評価コンテキストを切り替えることが出来ます。

例のようにinstance_evalを使うと、privateなメソッドを呼び出したり、アクセサの定義されていないインスタンス変数を参照することが出来ます。

また、class_evalというメソッドもあります。これはクラスを引数に取り、文字列またはブロックをそのクラス定義のコンテキストで評価します。

module_evalclass_evalのエイリアスなので機能は同じです。文脈に応じて使い分けます。

次のページでは、セッター/ゲッター系のメソッドとbindingについて説明します。