module Decorator
def method_hook_once(&block)
@_method_hook ||= []
@_method_hook << block
end
def method_added(sym)
return if @_defining
@_defining = true
if @_method_hook && !@_method_hook.empty?
f = instance_method(sym)
old = @_method_hook.pop
r = lambda{|*args| old.call(f.bind(self), *args)}
define_method sym, r
end
ensure
@_defining = false
end
end
class A
extend Decorator
def self.mul(a)
method_hook_once{|f, *args|
f.call(*args)*a
}
end
mul(2)
def answer
21
end
mul(3)
def three
3
end
end
x = A.new
p x.answer
p x.three