Mixin question

i have this

   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

===============================================================================

Ara.T.Howard schrieb:

(code snipped)

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) !!!

HTH,
Pit

"Ara.T.Howard" <Ara.T.Howard@noaa.gov> schrieb im Newsbeitrag
news:Pine.LNX.4.60.0407011009461.25990@harp.ngdc.noaa.gov...

i have this

   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"
   "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...

Does this help?

module M
  def self.included(cl)
    cl.instance_eval do
      instance_methods.each do |meth|
        define_method(meth) do |*args|
          p args
        end
      end
    end
  end

  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

Of course the method definition has to be made a bit smarter.

Regards

    robert