From: Ken Bloom Date: 2006-09-08T23:56:09+09:00 Subject: Re: [CHALLENGE] better alias_method On Fri, 08 Sep 2006 14:34:39 +0900, ara.t.howard wrote: > i've been wanting a better alias_method for quite some time. essentially i'd > like a way out of the trap where executing > > alias_method '__fubar__', 'fubar' > > goes haywire when __fubar__ already exists. we've all seen it happen before. > > anyhow. the interface it'd like would be It would be nice to have this built in to the language -- a way to blur the difference between overriding an inherited method and overriding a method defined on the current class, so that `super' would call whatever the previous version of the was. Try this idea on for size. I wrote it a few days ago. Look at the unit tests at the end to see how it's intended to be used. I think a little syntactic sugar would be nice, but it gets the job done. class Module private def override(method_name,&block) begin #case 1: I'm overriding a method defined on this object old_method=instance_method(method_name) alias_for_old=unused_alias alias_method alias_for_old, method_name rescue NameError begin #case 2: I'm overriding a method that I inherit from old_method=superclass.instance_method(method_name) rescue NameError #case 3: I'm not overriding anything. Just use a simple #function that we can call without side effects old_method=Object.instance_method(:nil?) end end define_method(method_name) do |*args| block.call(old_method.bind(self),*args) end end def unused_alias newalias=nil while newalias==nil or instance_methods.include?(newalias) newalias=:"__kenoverride__#{rand(10**20)}__" end newalias end end if __FILE__==$0 require 'test/unit' class TestOverride < Test::Unit::TestCase def setup eval <<-"end;" class A def foo; "a"; end end end; end def test_alias assert_nothing_raised do eval <<-"end;" class A override(:foo){|old| old.call+"b"} end end; end assert_equal A.new.foo,"ab" end def test_inherit assert_nothing_raised do eval <<-"end;" class B