Pit Capitain
7/31/2007 9:51:00 PM
2007/7/31, ara.t.howard <ara.t.howard@gmail.com>:
> i played some cannot seem to come up with a way to avoid having the
> stack of modules and also maintain super semantics across multiple
> invocations - anyone else have a go?
Ara, I didn't mean you don't need a stack of modules, but you don't
need to store the modules in an array (yet).
> just playing now. patches welcome! ;-)
Not a patch, but a slightly different implementation based on your idea:
class C
def foo() 'f' end
def bar() 'b' end
def foobar() foo + bar end
end
c = C.new
p c.foobar # => "fb"
class C
redefining do
def foo() super + 'oo' end
end
end
p c.foobar # => "foob"
class C
redefining do
def bar() super + 'ar' end
end
end
p c.foobar # => "foobar"
class C
redefining do
def foo() super.reverse end
def bar() super.reverse end
end
end
p c.foobar # => "oofrab"
### the implementation
BEGIN {
class Class
def redefining &block
unless defined? @_org
org_mod = Module.new
@_org = { :mod => org_mod }
include org_mod
end
m = Module.new(&block)
(m.instance_methods(false) & instance_methods(false)).each do |method|
@_org[method] = instance_method method
@_org[:mod].module_eval <<-EOC
def #{method}(*a, &b)
org = self.class.instance_variable_get("@_org")
org["#{method}"].bind(self).call(*a, &b)
end
EOC
remove_method method
end
include m
end
end
}
I used the old way of getting at the original method (storing it
somewhere), because I'm not sure whether the garbage collector could
remove it if you only remember it's object_id.
Regards,
Pit