[Ruby] メタプログラミングRuby 第2章 まとめ (動的メソッド)
2章のキーワード
- 動的ディスパッチ
- パターンディスパッチ
- define_method()
- Method Missing
- ゴーストメソッド
- ブランクスレート
はじめに
メソッドを動的に呼び出す
普通に呼び出す例
obj = TestClass.new
obj.test_method(arg)
動的に呼び出す例
obj = TestClass.new obj.send(:test_method, arg)
(この技術を「動的ディスパッチ」という)
動的ディスパッチ
プライベートメソッドも呼び出せる
(public_send()はレシーバのプライバシー範囲を遵守する)
- Test::Unitではこの動的ディスパッチが使われている
testではじまるメソッドをまず格納して、それぞれをsend()メソッドで実行している
(細かくは別名の__send__()メソッド:http://ref.xaio.jp/ruby/classes/object/__send__))
- "__"ではじまるメソッドは予約済みメソッドといい、安易に変更を加えられないよう中
- Test::Unitのようなライブラリはメタプロによる挙動の変更を防ぐため、このような予約済みメソッドを呼び出している
- この技術を「パターンディスパッチ」という
define_method()
動的にメソッドを定義する方法
普通に定義する場合
class TestClass def test_method(arg) arg * 2 end end
動的に定義する場合
define_method ${つくりたいメソッド名} do |${つくったメソッドに与えたい引数}| ${メソッドの内容} #==>ここは同じ end ↓ class TestClass define_method :test_method do |arg| arg * 2 end end
Method Missing
- Rubyではコンパイラがメソッド呼び出しを制限することはない=「存在しないメソッドも呼び出せる!」
- メソッドを呼び出す際、継承チェーンを探索しても見つからないときは、method_missing()を呼び出す
- 試しに呼び出してみる(privateメソッドだがsend()メソッドで呼び出せる)
obj.send :method_missing, :test_method # => NoMethodError: undefined method 'test_method' for # *********
- method_missing()をオーバーライドすると、実際に存在しないメソッドを呼び出すことができる
- これを「ゴーストメソッド」という
ブランクスレート
Builderライブラリ
- XML生成ライブラリ
require 'builder' xml = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) xml.coder{ xml.name 'のうじる', :nickname => 'brain' xml.langage 'Ruby' }
↓
<coder> <name nickname= 'brain'>のうじる</name> <language>Ruby</language> </coder>
動的プロキシ
- オブジェクトがゴーストメソッドを受け取り、なんらかのロジックを適用してから他のオブジェクトに転送すること