Hi Su,
The difference between undef_method and remove_method is, as you
point out, that undef_method marks the method as undefined.
This difference is most simply demonstrated with inheritance: if method dispatch reaches an
undefined method, it stops looking for the method and gives an error. However,
remove_method eliminates the method entirely, and the next ancestor will then
be considered.
In code:
class A
def foo; 'foo'; end
def bar; 'bar'; end
end
class B < A
def foo; 'B foo'; end
def bar; 'B bar'; end
remove_method :foo
undef_method :bar
end
class C < B
end
C.new.foo #=> 'foo'
C.new.bar #=> NoMethodError: undefined method `bar' for #<C:0x0000010161f7e0>
Regarding Marshal.dump, If you use remove_method instead of undef_method, you will
in fact be able to dump the object again:
obj = Object.new
def obj.foo
end
Marshal.dump(obj) #=> TypeError: singleton can't be dumped
class << obj
remove_method :foo
end
Marshal.dump(obj) #=> "\x04\bo:\vObject\x00"
The (simplified) technical reason why undef_method doesn't work and remove_method does,
regarding Marshal.dump, is that undef_method leaves the undefined flag as additional state
in the singleton class, whereas remove_method will leave `obj` with an empty singleton class,
identical to Object.
Hope this helps,
Michael Edgar
adgar@carboni.ca
http://carboni.ca/
···
On Apr 17, 2011, at 6:37 PM, Su Zhang wrote:
Hello,
According to the book Programming Ruby by Dave Thomas, "an
undefined method still exists - it is simply marked as being undefined."
Why is it not completely removed?
I find this somewhat related to the fact that an object still cannot be
dumped after "undefing" its singleton methods.
obj = Object.new
def obj.foo
end
p obj.respond_to? :foo # => true
class << obj
undef foo
end
p obj.respond_to? :foo # => true
Marshal.dump(obj) # => error
--
Posted via http://www.ruby-forum.com/\.