From: Rick DeNatale Date: 2007-06-15T10:55:14+09:00 Subject: Re: class destruction (evil genius metaprogramming) On 6/14/07, Giles Bowkett 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 > => # > >> kermit.show > => "it's the muppet show!" > >> class Muppet > >> remove_method(:show) > >> end > => Muppet > >> kermit.show > NoMethodError: undefined method `show' for # > 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 # > 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 # > 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/