From: Timothy Goddard Date: 2006-11-01T16:10:09+09:00 Subject: Re: Difference between define_method and def method; end Rune Hammersland wrote: > On 31. okt. 2006, at 17:10, ara.t.howard@noaa.gov wrote: > > On Tue, 31 Oct 2006, Rune Hammersland wrote: > >> # Try to redefine method and call super. > >> class Child < Parent > > > > you are not redefining the method here, you are redefining the class. > > if you simply redefine the method it does what you expect: > > > > harp:~ > cat a.rb > > class Parent > > def lol() puts "P: LOL" end > > end > > > > class Child < Parent > > def lol() puts "C: LOL" end > > end > > > > c = Child.new > > Child.class_eval { undef_method :lol } > > > > class Child #< Parent > > def lol > > print "LOL: " > > super > > rescue NameError => e > > puts e.to_s > > end > > end > > > > c.lol > > > > harp:~ > ruby a.rb > > LOL: superclass method `lol' disabled > > That is actually the same output I had. My problem (and excuse me for > not > stating it clearly) is that if I use define_method after undef_method: > > Child.class_eval { undef_method :lol } > c.lol # raises exception (of course) > > class Child; def lol() print "LOL: "; super end; end > c.lol # raises exception (superclass method disabled) > > Child.class_eval { define_method(:lol) { print "LOL: "; super } } > c.lol # prints "LOL: P: LOL" > > So you see: defining the method using the def ... end block raises an > exception if you call super after the method has been undefined, while > defining it using define_method does not. I expected it to either > raise or not > raise the exception in both cases (but do the same for both). > > I hope that clarified it (although I'm not sure it did, as explaining > things > can be hard to do even in your native language). > > .. or am I still redefining the class using the class ... end block? > > -- > Vennlig Hilsen / Regards > Rune Hammersland Hmm, very odd! You can get around this by doing something like this: class Object def supercall(meth, *args) method_name = meth.to_s current_class = self.class m = nil until m raise NoMethodError if current_class == Object current_class = current_class.superclass if current_class.instance_methods.include?(method_name) m = current_class.instance_method(method_name) end end m.bind(self).call(*args) end end You then replace the "super" keyword with a supercall(:foo) in your example and it works. This is much slower though.