jib:~ > cat a.rb
module M
def bar @bar = 42
super
end
end
class Foo
attr :bar
def initialize @bar = 'bar'
end
end
foo = Foo.new
p foo.bar
class Foo
include M # of course this acts as super - it does not override
end
p foo.bar
jib:~ > ruby a.rb
"bar"
and i want it to print "bar", "42". i'm looking for a way to overide all of a
classes methods via a module (or some other trick) without needing to extend
individual objects and without simply opening up the class and redefining
everything. in otherwords a simple way to override a bunch of bundled methods
at once. it seems like this must be possible but my brain isn't firing on all
fours today...
-a
···
--
EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen
i'm looking for a way to overide all of a classes methods via a module
> (or some other trick) without needing to extend individual objects and
> without simply opening up the class and redefining everything. in
> otherwords a simple way to override a bunch of bundled methods
at once.
Hi Ara,
you could try this:
require 'set'
class Module
def override *methods
methods.map! { |method| method.to_s }
methods = Set.new( methods ) & instance_methods( false )
unless methods.empty?
mod = Module.new
methods.each do |method|
mod.send :define_method, method, instance_method( method )
remove_method method
end
include mod
end
end
end
This code creates a new module, moves some methods from the original module into the new one, removes the original methods, an then includes the new module. You would call "override" like this:
module M
def bar @bar = 42
super
end
def self.append_features mod
mod.override :bar
super
end
end
class Foo
attr :bar
def initialize @bar = 'bar'
end
end
foo = Foo.new
p foo.bar # ==> "bar"
class Foo
include M
end
p foo.bar # ==> 42
The result is the following:
p Foo.ancestors # ==> [Foo, M, #<Module:0x2a68cf0>, Object, Kernel]
with the original "bar" being defined in the anonymous module.
!!! Note that this overriding doesn't work if the overridden method calls "super" itself (see ruby-talk:75286) !!!