今度こそinstance_evalとmodule_evalを理解してもらった(問題の答え)
(id:akm:20100226:1267134143) で出題された問題の答えです。
まずは前提から
irbを起動して、実際に試しながらやってみます。
obj = Object.new #=> #<Object:0x101171ef0> class A end #=> nil
objというObjectのインスタンスと、Aというクラスがあります。
block = Proc.new do def foo 'foo' end end #=> #<Proc:0x000000010115e698@(irb):6>
という、fooメソッドを定義するblockがあります。
Ans1. objに特異メソッドとしてfooを定義するコード
obj.instance_eval(&block) #--- 1. #=> nil obj.singleton_methods #--- 2. #=> ["foo"] obj.foo #=> "foo"
- (id:akm:20100226:1267134143)に特異メソッドの書き方が3つ挙げられていますが、ブロックを渡せそうなのはinstance_evalです。「&block」のように引数名の前に&をつけると、ブロックをオブジェクトとして引数に受け取ることができます。
- 特異メソッドが追加されたことを確認できました。(singleton_methodsは特異メソッドが調べられます。)
Ans2. Aにインスタンスメソッドとしてfooを定義するコード。
A.module_eval(&block) #--- 1. #=> nil A.instance_methods(false) #--- 2. #=> ["foo"] a = A.new #=> #<A:0x101117c20> a.foo #=> "foo"