On 6/14/07, Giles Bowkett <gilesb / gmail.com> wrote:
> I want to write a module which, when included in another module,
> destroys every method of a class in that module. I realize this isn't
> really a very useful thing to do, but I want to do it to see if it can
> be done. I want to actually include the module and have it replace all
> existing methods of this class with just one method.
>
> In Python you can change an object's class in the middle of your
> program by reassigning its magical __class__ variable. That would be a
> very simple way to implement this idea. Doesn't seem possible here,
> though.
>
> Here's an attempt which failed:
>
> >> class Muppet
> >>   def show
> >>     "it's the muppet show!"
> >>     end
> >>   end
> => nil
> >> kermit = Muppet.new
> => #<Muppet:0x123129c>
> >> kermit.show
> => "it's the muppet show!"
> >> class Muppet
> >>   remove_method(:show)
> >>   end
> => Muppet
> >> kermit.show
> NoMethodError: undefined method `show' for #<Muppet:0x123129c>
>         from (irb):36
>         from :0
>
> So far so good, but I want to get rid of *every* method. Doing what I
> just did programmatically, iterating over all available methods,
> that's the thing which still eludes me.
>
> None of these attempts work:
>
> >> kermit.methods.each{|m| class << Muppet ; (remove_method(m)) ; end}
> NameError: undefined local variable or method `m' for #<Class:Muppet>
>         from (irb):43
>         from (irb):43:in `each'
>         from (irb):43
>         from :0
> >> kermit.methods.each{|m| class Muppet; remove_method(m.to_sym) ; end}
> NameError: undefined local variable or method `m' for Muppet:Class
>         from (irb):44
>         from (irb):44:in `each'
>         from (irb):44
>         from :0
> >> kermit.methods.each{|m| Muppet.class_eval(remove_method(m))}
> NoMethodError: undefined method `remove_method' for #<Object:0x349f4>
>         from (irb):45
>         from (irb):45:in `each'
>         from (irb):45
>         from :0
>
> I have to admit, it's not necessarily a bad thing if this task proves
> impossible, but I feel like it *should* be possible.

kermit.class.instance_methods(false).each{|m|
Muppet.instance_eval("remove_method #{m.inspect}")}

Note 1. kermit.methods will return all methods inherited or not.
Note 2. remove method is a class method, so it's evaluated in the
context of the class object, hence Muppet.instance_eval
Note 3: you could alternatively pass symbols for the method names

kermit.class.instance_methods(false).each{|m|
Muppet.instance_eval("remove_method :#{m}")}



-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/