柴ブログ

プログラミング奮闘記

メタプログラミングRuby3章読んで学んだこと

はじめに

知人のエンジニアの方達とメタプログラミングRubyの輪読会をし、3章を読んで学んだことをまとめ。

メソッド

send

sendメソッドはオブジェクトのメソッド名を第一引数に取り、第二引数にそのメソッドの引数を渡し、メソッドを実行できる。

privateメソッドも呼び出せてしまうので、publicメソッドのみ呼び出すようにしたい場合はpublic_sendを使う。

public_sendメソッドでprivateメソッドを呼ぼうとするとNoMethodErrorをraiseする。

docs.ruby-lang.org

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"

docs.ruby-lang.org

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>)

docs.ruby-lang.org