Prev: cucumber
Next: Safari display problems
From: Chuck Remes on 11 Aug 2010 11:32 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
From: Jesús Gabriel y Galán on 11 Aug 2010 12:11 On Wed, Aug 11, 2010 at 5:32 PM, Chuck Remes <cremes.devlist(a)mac.com> 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 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 > > I've managed to do it with a local variable, instead of an instance variable: class Foo def self.now "Foo's now" end end class Bar def initialize bar = 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.
From: Chuck Remes on 12 Aug 2010 14:18 On Aug 11, 2010, at 11:11 AM, Jesús Gabriel y Galán wrote: > On Wed, Aug 11, 2010 at 5:32 PM, Chuck Remes <cremes.devlist(a)mac.com> 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 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. >> >> 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" > > I've managed to do it with a local variable, instead of an instance variable: > > class Foo > def self.now > "Foo's now" > end > end > > class Bar > def initialize > bar = 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. 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
From: hemant on 12 Aug 2010 15:15 Hi, On Thu, Aug 12, 2010 at 11:48 PM, Chuck Remes <cremes.devlist(a)mac.com> wrote: > >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 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 -- 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
|
Pages: 1 Prev: cucumber Next: Safari display problems |