injecting an instance method into another class' class method

Discussion in 'Ruby' started by Chuck Remes, Aug 11, 2010.

  1. Chuck Remes

    Chuck Remes Guest

    I'd like to reopen a class Foo and redefine one of its methods to use an instance method from class Bar. I can't seem to figure out how to do it or even if it is possible.

    I tried lots of different techniques and none have worked, so here I am asking for a bit of help. An example of one of the techniques I tried is included below.

    class Foo
    def self.now
    Time.now.to_i
    end
    end

    class Bar
    def initialize
    @bar = proc { now }

    Bar.class_eval <<-code
    class Foo
    def Foo.now
    @bar.call
    end
    end
    code
    end

    def now
    puts "bar now called"
    end
    end


    I would like Foo.now to return Time.now.to_i for the normal case. However, after an instance of Bar is created, I would like the Bar instance to redefine Foo.now to call the #now instance method of Bar.

    This is what the output should look like:

    ruby-1.9.1-p378 > Foo.now
    => 1281540640
    ruby-1.9.1-p378 > Bar.new
    bar now
    => #<Bar:0x00000101216268 @bar=#<Proc:0x000001012161c0@(irb):41>>
    ruby-1.9.1-p378 > Foo.now
    => "bar now called"


    Is it possible to do this?

    cr
     
    Chuck Remes, Aug 11, 2010
    #1
    1. Advertising

  2. On Wed, Aug 11, 2010 at 5:32 PM, Chuck Remes <> wrote=
    :
    > I'd like to reopen a class Foo and redefine one of its methods to use an =

    instance method from class Bar. I can't seem to figure out how to do it or =
    even if it is possible.
    >
    > I tried lots of different techniques and none have worked, so here I am a=

    sking for a bit of help. An example of one of the techniques I tried is inc=
    luded below.
    >
    > class Foo
    > =A0def self.now
    > =A0 =A0Time.now.to_i
    > =A0end
    > end
    >
    > class Bar
    > =A0def initialize
    > =A0 =A0@bar =3D proc { now }
    >
    > =A0 =A0Bar.class_eval <<-code
    > =A0 =A0class Foo
    > =A0 =A0 =A0def Foo.now
    > =A0 =A0 =A0 =
    > =A0 =A0 =A0end
    > =A0 =A0end
    > =A0 =A0code
    > =A0end
    >
    > =A0def now
    > =A0 =A0puts "bar now called"
    > =A0end
    > end
    >
    >
    > I would like Foo.now to return Time.now.to_i for the normal case. However=

    , after an instance of Bar is created, I would like the Bar instance to red=
    efine Foo.now to call the #now instance method of Bar.
    >
    > This is what the output should look like:
    >
    > ruby-1.9.1-p378 > Foo.now
    > =A0=3D> 1281540640
    > ruby-1.9.1-p378 > Bar.new
    > bar now
    > =A0=3D> #<Bar:0x00000101216268 @bar=3D#<Proc:0x000001012161c0@(irb):41>>
    > ruby-1.9.1-p378 > Foo.now
    > =A0=3D> "bar now called"
    >
    >
    > Is it possible to do this?
    >
    > cr
    >
    >


    I've managed to do it with a local variable, instead of an instance variabl=
    e:

    class Foo
    def self.now
    "Foo's now"
    end
    end

    class Bar
    def initialize
    bar =3D proc {now}
    class << Foo; self; end.class_eval do
    define_method:)now) do
    bar.call
    end
    end
    end

    def now
    "Bar's now"
    end
    end

    puts Foo.now
    puts Bar.new.now
    puts Foo.now

    $ ruby redefine.rb
    Foo's now
    Bar's now
    Bar's now

    The problem with an instance variable is that you need to have self as
    Bar's instance in order for it to work. So if you can use a local
    variable and use closures, it will work, as shown above.

    Jesus.
     
    Jesús Gabriel y Galán, Aug 11, 2010
    #2
    1. Advertising

  3. Chuck Remes

    Chuck Remes Guest

    On Aug 11, 2010, at 11:11 AM, Jes=FAs Gabriel y Gal=E1n wrote:

    > On Wed, Aug 11, 2010 at 5:32 PM, Chuck Remes <> =

    wrote:
    >> I'd like to reopen a class Foo and redefine one of its methods to use =

    an instance method from class Bar. I can't seem to figure out how to do =
    it or even if it is possible.
    >>=20
    >> I tried lots of different techniques and none have worked, so here I =

    am asking for a bit of help. An example of one of the techniques I tried =
    is included below.
    >> [snip]
    >> I would like Foo.now to return Time.now.to_i for the normal case. =

    However, after an instance of Bar is created, I would like the Bar =
    instance to redefine Foo.now to call the #now instance method of Bar.
    >>=20
    >> This is what the output should look like:
    >>=20
    >> ruby-1.9.1-p378 > Foo.now
    >> =3D> 1281540640
    >> ruby-1.9.1-p378 > Bar.new
    >> bar now
    >> =3D> #<Bar:0x00000101216268 @bar=3D#<Proc:0x000001012161c0@(irb):41>>
    >> ruby-1.9.1-p378 > Foo.now
    >> =3D> "bar now called"

    >=20
    > I've managed to do it with a local variable, instead of an instance =

    variable:
    >=20
    > class Foo
    > def self.now
    > "Foo's now"
    > end
    > end
    >=20
    > class Bar
    > def initialize
    > bar =3D proc {now}
    > class << Foo; self; end.class_eval do
    > define_method:)now) do
    > bar.call
    > end
    > end
    > end
    >=20
    > def now
    > "Bar's now"
    > end
    > end
    >=20
    > puts Foo.now
    > puts Bar.new.now
    > puts Foo.now
    >=20
    > $ ruby redefine.rb
    > Foo's now
    > Bar's now
    > Bar's now
    >=20
    > The problem with an instance variable is that you need to have self as
    > Bar's instance in order for it to work. So if you can use a local
    > variable and use closures, it will work, as shown above.


    Ah, excellent! I was trying to figure out how to use a closure for this =
    purpose, but my mind got all turned inside out.

    I'm somewhat familiar with getting the singleton class of a class using =
    the "class << self;self;end" syntax, but I'm not sure what is happening =
    here:

    class << Foo
    self # what is self here? Foo? Bar? instance of Bar?
    end

    My inline questions lay it out.

    I'd really like to understand how that part of it is working. I =
    understand the mechanics of the remaining code.

    cr
     
    Chuck Remes, Aug 12, 2010
    #3
  4. Chuck Remes

    hemant Guest

    Hi,

    On Thu, Aug 12, 2010 at 11:48 PM, Chuck Remes <> wrot=
    e:
    >
    >I'm somewhat familiar with getting the singleton class of a class using th=

    e "class << self;self;end" syntax, but I'm not sure what is >happening here=
    :
    >
    > class << Foo
    > =A0self # what is self here? Foo? Bar? instance of Bar?
    > end


    since classes are objects too , for "class << Foo; self; end" self is
    singleton (or eigenclass) class of the class object. Typically class
    methods of a class are defined in its singleton class.

    http://yugui.jp/articles/846


    --=20
    Let them talk of their oriental summer climes of everlasting
    conservatories; give me the privilege of making my own summer with my
    own coals.

    http://gnufied.org
     
    hemant, Aug 12, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin P. Hellwig
    Replies:
    1
    Views:
    383
    Martin P. Hellwig
    Mar 26, 2010
  2. George  Moschovitis

    Injecting methods from one class into another.

    George Moschovitis, Jan 25, 2005, in forum: Ruby
    Replies:
    27
    Views:
    256
    Zach Dennis
    Feb 5, 2005
  3. johanatan
    Replies:
    70
    Views:
    636
  4. Raj Singh
    Replies:
    2
    Views:
    212
    Rick DeNatale
    May 29, 2008
  5. Greg Hauptmann
    Replies:
    9
    Views:
    262
    Loren Segal
    Jun 16, 2008
Loading...

Share This Page