On Mar 9, 2006, at 11:03 AM, Dirk van Deun wrote: > A very short and simple question: is there a function to "unextend" an > object ? Obviously it does not exist under that name, nor could I > find > anything like it. It would be useful though to do "traits": > > dirk = Human.new > dirk.extend(actor) > dirk.work > if dirk.income < PITTANCE > dirk.unextend(actor) > dirk.extend(waiter) > dirk.work > end > > Dirk van Deun > -- > Ceterum censeo Redmond delendum > I don't believe there is an unextend method, however if you're willing to live with some dark magic that I haven't extensively tested: irb(main):001:0> require 'quasiextender' => true irb(main):002:0> class A irb(main):003:1> def each irb(main):004:2> yield 1 irb(main):005:2> end irb(main):006:1> include QuasiExtender irb(main):007:1> end => A irb(main):008:0> a = A.new => #<A:0x370718> irb(main):009:0> a.quasi_extend(Enumerable) => [Enumerable] irb(main):010:0> a.map { |x| x.to_s } => ["1"] irb(main):011:0> a.quasi_retract(Enumerable) => [] irb(main):012:0> a.map { |x| x } NoMethodError: undefined method `map' for #<A:0x370718 @__quasi_extensions=[]> from ./quasiextender.rb:30:in `method_missing' from (irb):12 And here's the evil code. Its actually not terribly long: % cat quasiextender.rb require 'delegate' module QuasiExtender def quasi_extend(mod) @__quasi_extensions ||= [] @__quasi_extensions << mod end def quasi_retract(mod) @__quasi_extensions ||= [] @__quasi_extensions.delete_if { |ext| ext == mod } end def method_missing(name, *args, &block) @__quasi_extensions ||= [] meth = nil found_mod = nil @__quasi_extensions.each do |ext| begin meth = ext.instance_method(name.to_sym) found_mod = ext rescue NameError, NoMethodError next else break end end if meth.nil? # we didn't find it super else sneaky_class = Class.new(SimpleDelegator) { include(found_mod) } sneaky_obj = sneaky_class.new(self) meth.bind(sneaky_obj).call(*args, &block) end end end