Defining object methods in initialize

I'd like to define methods on initialize that are specific for the created
object. However it seems that the few lines of code below is defining them
somewhere else since they are 'overwriting' each other:

···

============
class Foo
def initialize(method_name, &block)
  self.class.send(:define_method, method_name, &block)
end
end

aa = Foo.new(:whoareyou) { puts "I am aa" }
bb = Foo.new(:whoareyou) { puts "I am bb" }

aa.whoareyou
# returns: "I am bb" - But I expect: "I am aa"
bb.whoareyou
# returns: "I am bb"

Foo.whoareyou
# undefined method ===> Good

Thanks!

martin

However it seems that the few lines of code below is defining them
somewhere else since they are 'overwriting' each other:

============
class Foo
def initialize(method_name, &block)
  self.class.send(:define_method, method_name, &block)
end

You're absoultely right about the methods being defined "somewhere
else", they're being defined in the class Foo, which both instances
share. If you want to define specific and different implementations
for the same method name you need to use singleton/instance
inheritance. Like this:

class Foo
def initialize(method_name, &block)
  c = class << self; self; end
  c.send(:define_method, method_name, &block)
end

That way each instance gets a private Class that they don't share.

Take the above with a grain of salt, I don't have an interpreter on
this computer, so I can test it to see if it works... This blog
article might be interesting if you care for a deeper explanation:

···

aa = Foo.new(:whoareyou) { puts "I am aa" }
bb = Foo.new(:whoareyou) { puts "I am bb" }

aa.whoareyou
# returns: "I am bb" - But I expect: "I am aa"
bb.whoareyou
# returns: "I am bb"

Foo.whoareyou
# undefined method ===> Good

Thanks!

martin

Note, you do not necessarily need instance methods in this case:

irb(main):001:0> Foo = Struct.new :whoareyou
=> Foo
irb(main):002:0> aa = Foo.new "I am aa"
=> #<struct Foo whoareyou="I am aa">
irb(main):003:0> bb = Foo.new "A am bb"
=> #<struct Foo whoareyou="A am bb">
irb(main):004:0> aa.whoareyou
=> "I am aa"
irb(main):005:0> bb.whoareyou
=> "A am bb"

Kind regards

  robert

···

On 04.03.2007 14:59, Martin Boese wrote:

I'd like to define methods on initialize that are specific for the created object. However it seems that the few lines of code below is defining them somewhere else since they are 'overwriting' each other:

============
class Foo
def initialize(method_name, &block)
  self.class.send(:define_method, method_name, &block)
end

aa = Foo.new(:whoareyou) { puts "I am aa" }
bb = Foo.new(:whoareyou) { puts "I am bb" }

aa.whoareyou # returns: "I am bb" - But I expect: "I am aa"
bb.whoareyou # returns: "I am bb"

Foo.whoareyou
# undefined method ===> Good

Thanks! Working!

···

On Sunday 04 March 2007 14:11, Tim Becker wrote:

> However it seems that the few lines of code below is defining them
> somewhere else since they are 'overwriting' each other:
>
> ============
> class Foo
> def initialize(method_name, &block)
> self.class.send(:define_method, method_name, &block)
> end
> end

You're absoultely right about the methods being defined "somewhere
else", they're being defined in the class Foo, which both instances
share. If you want to define specific and different implementations
for the same method name you need to use singleton/instance
inheritance. Like this:

class Foo
def initialize(method_name, &block)
  c = class << self; self; end
  c.send(:define_method, method_name, &block)
end
end

That way each instance gets a private Class that they don't share.

Take the above with a grain of salt, I don't have an interpreter on
this computer, so I can test it to see if it works... This blog
article might be interesting if you care for a deeper explanation:

Ola Bini: Programming Language Synchronicity: singleton class

> aa = Foo.new(:whoareyou) { puts "I am aa" }
> bb = Foo.new(:whoareyou) { puts "I am bb" }
>
> aa.whoareyou
> # returns: "I am bb" - But I expect: "I am aa"
> bb.whoareyou
> # returns: "I am bb"
>
> Foo.whoareyou
> # undefined method ===> Good
> ============
>
>
> Thanks!
>
> martin