リフレクション
リフレクションは、実行時にオブジェクトに関する情報を調べる処理です。methods
メソッドを呼び出すと、クラスに使用できるメソッドが分かります。Rubyのあらゆるものの基本クラスはObjectなので、Rubyのすべてのオブジェクトで使用できるメソッドを調べてみましょう。
irb(main):001:0> o = Object.new => #<Object:0x3f8feb4> irb(main):002:0> o.methods => ["inspect", "taguri", "clone", "public_methods" , "taguri=", "display", "instance_variable_defined ?", "equal?", "freeze", "methods", "respond_to?", ...many more methods listed...
methods
を呼び出した結果は、そのオブジェクトで使用できる各メソッド名が格納された文字列の配列です。クラスはハッシュと同じようなものと考えることができます。methods
を呼び出すのは、そのハッシュテーブルのキー一覧を取得するようなものです。
もちろん、どんなメソッドがあるかを調べることができても、実際にメソッドを使って何かできなければ、面白くもなんともありません。メソッドを呼び出すには、send
メソッドを使います。次の2つの操作は同等です。
irb(main):003:0> o.inspect => "#<Object:0x3f8feb4>" irb(main):004:0> o.send "inspect" => "#<Object:0x3f8feb4>"
Rubyでは、クラスでmethod_missing
メソッドを定義することによって、未定義メソッドを処理できます。
irb(main):139:0> class Object irb(main):140:1> def method_missing(*args) irb(main):142:2> puts args irb(main):143:2> end irb(main):144:1> end => nil irb(main):145:0> o.foobar 1, 2, 3 foobar 1 2 3 => nil
このように、method_missing
に渡される引数には、要求されたメソッドと、そのメソッドに渡されたすべての引数が含まれます。おそらく、次のように定義するのが望ましいでしょう。
def method_missing(method, *args)