Undefine Method Only Marks the Method Undefined

S

Su Zhang

Hello,

According to the book Programming Ruby by Dave Thomas, "an
unde=EF=AC=81ned method still exists - it is simply marked as being unde=EF=
=AC=81ned."
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 =3D Object.new

def obj.foo
end

p obj.respond_to? :foo # =3D> true

class << obj
undef foo
end

p obj.respond_to? :foo # =3D> true

Marshal.dump(obj) # =3D> error

-- =

Posted via http://www.ruby-forum.com/.=
 
M

Michael Edgar

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 #=3D> 'foo'
C.new.bar #=3D> 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 =3D Object.new
def obj.foo
end

Marshal.dump(obj) #=3D> TypeError: singleton can't be dumped

class << obj
remove_method :foo
end

Marshal.dump(obj) #=3D> "\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
(e-mail address removed)
http://carboni.ca/
 
J

Josh Cheek

Hello,

According to the book Programming Ruby by Dave Thomas, "an
unde=EF=AC=81ned method still exists - it is simply marked as being unde= =EF=AC=81ned."
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 =3D Object.new

def obj.foo
end

p obj.respond_to? :foo # =3D> true

class << obj
undef foo
end

p obj.respond_to? :foo # =3D> true

Marshal.dump(obj) # =3D> error


I assume because the intuition is that undefining a method on an object
means the object should raise the undefined error when you try to call it.
But simply removing it would not prevent Ruby from finding an inherited
version of the method.

ie

o =3D Object.new

o.to_s # =3D> "#<Object:0x0000010086a460>"

def o.to_s
"o#to_s"
end

o.to_s # =3D> "o#to_s"

class << o
remove_method :to_s
end

o.to_s # =3D> "#<Object:0x0000010086a460>"



It still has a to_s method, because it inherits one from Object. What if yo=
u
want it to not respond to that one? You can't undefine the method on object=
,
or every object loses it's inherited to_s method. So you need to interrupt
dispatch when this method is called. Hence undef simply raises the same
error you would have gotten if it hadn't found the method:


o =3D Object.new

o.to_s # =3D> "#<Object:0x0000010086a488>"

def o.to_s
"o#to_s"
end

o.to_s # =3D> "o#to_s"

class << o
undef :to_s
end

o.to_s # =3D>
# ~> -:15:in `<main>': undefined method `to_s' for
#<Object:0x0000010086a488> (NoMethodError)
 
S

Su Zhang

Thank you - Michael and Josh, now this makes perfect sense to me. It's
funny how I wasn't aware of the existence of `remove_method' at all!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top