メタプログラミングRuby3章読んで学んだこと
はじめに
知人のエンジニアの方達とメタプログラミングRubyの輪読会をし、3章を読んで学んだことをまとめ。
メソッド
send
send
メソッドはオブジェクトのメソッド名を第一引数に取り、第二引数にそのメソッドの引数を渡し、メソッドを実行できる。
privateメソッドも呼び出せてしまうので、publicメソッドのみ呼び出すようにしたい場合はpublic_send
を使う。
public_send
メソッドでprivateメソッドを呼ぼうとするとNoMethodError
をraiseする。
define_method
メソッドを動的に定義できるメソッド。 言葉で説明するよりサンプルで動かした方が分かりやすい。
irb(main):001:1* class Hoge irb(main):002:1* define_method("fuga") {"fuga"} irb(main):003:0> end => :fuga irb(main):004:0> Hoge.new.fuga => "fuga"
Hogeクラスに"fuga"
を返すfugaメソッドを動的に生やす例。
define_method
メソッドの第一引数は定義したいメソッド名をStringかSymbolで指定し、第二引数でProcやメソッドを渡すとその返り値が定義したメソッドの返り値になる。
上記のサンプルでは第二引数はなくブロックを渡す例だが、第二引数でProcを渡すなら下記のようになる。
irb(main):001:1* class Hoge irb(main):002:1* define_method("fuga", -> {"fuga"}) irb(main):003:0> end => :fuga irb(main):004:0> Hoge.new.fuga => "fuga"
define_singleton_method
先程のdefine_method
と違い、特異メソッドを生やす。
irb(main):001:1* class Hoge irb(main):002:0> end => nil irb(main):003:0> hoge = Hoge.new => #<Hoge:0x00007f92c5959ae8> irb(main):004:0> hoge.define_singleton_method("fuga") {"fuga"} => :fuga irb(main):005:0> hoge.fuga => "fuga" irb(main):006:0> hogehoge = Hoge.new => #<Hoge:0x00007f92c5962508> irb(main):007:0> hogehoge.fuga => NoMethodError (undefined method `fuga' for #<Hoge:0x00007f92c5962508>)