const_missingでプロキシモジュールを作る
Module#const_missingでモジュールに定数やクラスが定義されていない場合の動作を指定できます。
- Object#method_missingのクラス版と考えてよいのかな。
- 引数で参照した定数の名前が渡されてきます。
これを利用して、返却するクラスを動的に差し替え可能なプロキシモジュールを書いてみました。
# 別のモジュールの定義を参照するプロキシモジュール。 # delegateを変更することでクラスの参照先を動的に変更可能 module Proxy @@deleate = nil def Proxy.const_missing(id) @@deleate ? @@deleate.const_get(id) : super end def Proxy.method_missing(name,*args, &block) @@deleate ? @@deleate.send( name, *args, &block ) : super end def Proxy.delegate=(delegate) @@deleate = delegate end end # テスト用モジュール1 module Test class Kitten def meow "meow!" end end def self.foo "foo" end NAME = "test" end # テスト用モジュール2 module Test2 class Kitten def meow "meow!"*3 # 3回鳴く。 end end NAME = "test2" end # 委譲先としてTestを指定。 # 「Proxy::Kitten」で「Test::Kitten」が返される Proxy.delegate = Test puts Proxy::Kitten.new.meow # => meow! puts Proxy::NAME # => test # 委譲先をTest2に変更。 # 「Proxy::Kitten」で「Test2::Kitten」が返される Proxy.delegate = Test2 puts Proxy::Kitten.new.meow # => meow!meow!meow! puts Proxy::NAME # => test2
実行結果です。
meow! test meow!meow!meow! test2