1月 152014
用途
Ruby版EventEmitterなどのincludeして既存クラスを拡張するタイプのライブラリを使う時に、mix-inされる関数と自分の関数の名前が衝突してしまう場合に有用。Ruby用のsocket.io実装を作っているんだけど、EventEmitter gemで定義されているemit関数を__emitに退避してemitを新たに自分で定義するのに使った。
alias_methodで関数名の衝突を回避する
module Fooをclass Barにincludeした時に、FooにもBarにも同じ関数を定義している場合、クラスの方に定義した関数の方が優先される。モジュールの方の、せっかくincludeでmix-inした関数は消滅してしまう
includeしたmoduleの方の関数fooも使いたい場合、includeしてすぐにalias_methodで別名に退避するとよい。
module Foo
def foo
puts "foo called!!"
end
end
class Bar
include Foo
alias_method :__foo, :foo ## fooを別名(__foo)に退避
def bar
puts "bar called!!"
end
def foo
puts "Bar's foo called.."
end
end
bar = Bar.new
bar.bar
bar.__foo # include後に退避したmoduleの関数が呼ばれる
bar.foo # include後に上書きした関数が呼ばれる
結果
bar called!!
foo called!!
Bar's foo called..
alias_methodのタイミング
関数の上書き定義後にalias_methodを使っても、退避できない。module Foo
def foo
puts "foo called!!"
end
end
class Bar
include Foo
def bar
puts "bar called!!"
end
def foo
puts "Bar's foo called.."
end
alias_method :__foo, :foo ## 上書き定義した後にエイリアスでの退避を試みる
end
bar = Bar.new
bar.bar
bar.__foo
bar.foo
fooも__fooも、どちらも上書き定義されたメソッドが呼ばれる。
bar called!!
Bar's foo called..
Bar's foo called..
ちなみにもちろんinclude前にalias_methodしても、NameError(undefined method)例外が起こる。