Re-define class method

I’ve got the following:

module ClassMethods
def class_method
“Class method”
end
end

class Thing
extend ClassMethods
end

Thing.class_method
=> “Class method”

… and I want to change the behaviour of that method at runtime. I
tried this:

Thing.send(:define_method, :class_method, lambda{ “replaced” })

… but I still get this:

Thing.class_method
=> “Class method”

Am I close? What’s the right way to do this?

Thanks,
David

On Jul 12, 2006, at 9:58 PM, David C. wrote:

end

Thing.class_method
=> “Class method”

Am I close? What’s the right way to do this?

OK - I’ve discovered that I can do this:

Thing.class.send(:define_method, :other_method, lambda{ “other” })
Thing.other_method
=> “other”

and even redefine it:

Thing.class.send(:define_method, :other_method, lambda{ “other
redefined” })
Thing.other_method
=> “other redefined”

but if I try this:

Thing.class.send(:define_method, :class_method, lambda{ “replaced” })
Thing.class_method
=> “Class method”

So it looks like I can replace class methods that I define at
runtime, but not the ones that were defined at load-time. Is that
correct? Am I missing a step?

Thanks,
David

Well, I discovered the solution, thanks to our friend google, and got
a much better understanding of singleton classes (though the fog
hasn’t completely dissipated). For anyone interested:

thing_singleton_class = class << Thing; self; end
thing_singleton_class.send(:define_method, :class_method, proc
{ “replaced” })

Thing.class_method
=> “replaced”

Cheers,
David

Hi –

On Thu, 13 Jul 2006, David C. wrote:

Well, I discovered the solution, thanks to our friend google, and got a much
better understanding of singleton classes (though the fog hasn’t completely
dissipated). For anyone interested:

thing_singleton_class = class << Thing; self; end
thing_singleton_class.send(:define_method, :class_method, proc { “replaced”
})

Thing.class_method
=> “replaced”

Don’t forget that you can do this much more concisely (unless you have
a specific need to go the long way round):

def Thing.class_method
“replaced”
end

David

Hi –

On Thu, 13 Jul 2006, David C. wrote:

to stick w/ the more cryptic version. Unless you have a different suggestion

  • I’m just getting my head wrapped around metaprogramming and singleton
    classes, so all suggestions are most welcome.

There’s an intermediate version, which might be usable depending on
how much you know in advance:

class << Thing
def class_method
“replaced”
end
end

When you need a less concise version, because you’re determining
things more dynamically, I would personally tend to use class_eval and
define_method without send:

meth = “class_method”
l = lambda { “replaced” }
(class << Thing; self; end).class_eval { define_method(meth,&l) }

And hopefully we’ll eventually have a Kernel#singleton_class method to
make it all a little neater :slight_smile:

David

On Jul 13, 2006, at 5:33 AM, [email protected] wrote:

a specific need to go the long way round):

def Thing.class_method
“replaced”
end

Thanks David. I definitely appreciate the conciseness of this, and
will use that when I know the type. The problem I’m working on
requires a solution to replacing singleton methods on arbitrary types
at runtime, so I think I have to stick w/ the more cryptic version.
Unless you have a different suggestion - I’m just getting my head
wrapped around metaprogramming and singleton classes, so all
suggestions are most welcome.

Thanks,
David

On 7/13/06, David C. [email protected] wrote:

at runtime, so I think I have to stick w/ the more cryptic version.
Unless you have a different suggestion - I’m just getting my head
wrapped around metaprogramming and singleton classes, so all
suggestions are most welcome.

Thanks,
David

You can use David’s method like this:

def redefine_method_for(klass)
def klass.class_method
“replaced”
end
end

redefine_method_for Thing

p Thing.class_method
#=> “replaced”

Regards,
Sean

On Jul 13, 2006, at 6:24 AM, [email protected] wrote:

meth = “class_method”
l = lambda { “replaced” }
(class << Thing; self; end).class_eval { define_method(meth,&l) }

Excellent! Much cleaner.

Thanks,
David

On Jul 13, 2006, at 7:47 AM, Sean O’Halpin wrote:

You can use David’s method like this:
#=> “replaced”
Unfortunately (actually, rather fortunately :wink: ), both the class and
the method name are determined at run time. David’s dynamic
suggestion (elsewhere in this thread) is working quite well.

Cheers, and thanks for the help!

David