Reputation: 967
Is it possible to remove a method from a single instance?
class Foo
def a_method
"a method was invoked"
end
end
f1 = Foo.new
puts f1.a_method # => a method was invoked
I can remove a_method from the class an from the already created object with this:
class Foo
remove_method(:a_method)
end
If I invoke a_method from the same object:
puts f1.a_method # => undefined method
If I create another object:
f2 = Foo.new
puts f2.a_method # => undefined method
How can I only remove a method from an specific single object?
Upvotes: 15
Views: 3674
Reputation: 63167
You can call undef_method
on the singleton class of the object you care about:
f1.singleton_class.undef_method(:a_method)
Don't confuse remove_method
and undef_method
. They look similar, but have quite different behaviour. The docs of undef_method
explain it as:
Prevents the current class from responding to calls to the named method. Contrast this with
remove_method
, which deletes the method from the particular class; Ruby will still search superclasses and mixed-in modules for a possible receiver.
Module#remove_method
...will delete a method from a particular Module/Class' method table.
That doesn't mean that the message (e.g. a_method
) can't still be sent to objects of that class.
It'll behave as if you didn't define a method implementation in that Module/Class, so regular inheritance behaviour will still occur: method resolution will continuing its search up the ancestor chain.
Here's an example:
class Parent
def m = "The parent implementation"
end
class Child < Parent
def m = "The child override"
remove_method :m # Behaves as if `m` was commented out above
end
p Child.new.m # => "The parent implementation"
Module#undef_method
... will define a special method in the Module/Class' method table with a special type (VM_METHOD_TYPE_UNDEF
), which behaves as if it had an implementation that just raises.
Attempting to call this method will find this stub, and terminate the search (not searching up the ancestor chain). Its implementation just raises.
class Parent
def m = "The parent implementation"
end
class Child < Parent
def m = "The child override"
undef_method :m # Behaves as if `m` was defined as `= raise NoMethodError`
end
p Child.new.m # => NoMethodError
Upvotes: 2