Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Object#sendで既存クラスにメソッドを追加したりエイリアスをはったりする

Object#send自体は、メソッドを呼び出す用法で以前使いました。
今回は既存クラスに既存のクラスに追加のメソッドを定義する方法を扱います。
具体的にはModule#define_methodをObject#sendします。
こんな感じです

String.send(:define_method, :answer) { 42 }
#=> :answer

"hoge".answer
#=> 42

引数はブロック引数を使います。

String.send(:define_method, :something) {|a,b| (a + b).to_s }
#=> :something

"hoge".something(1, 2)
#=> "3"

エイリアスもこの通り。

String.send(:alias_method, :to_default_s, :to_s)
#=> String

これらは#class_evalと使い手が似ています。

String.class_eval { def nya; 32; end }

"bar".nya
#=> 32

どの方法も効果範囲が広く、カプセル化もクソもあったものじゃないです。
また、動的定義は遅くなる傾向があるため、パフォーマンス重視の局面ではやらない方が無難です。

滅多に呼び出さないメソッドで、
かつ短く書きたいならこういう方法もある...という認識でお願いします。