Removing / defining a class method

You can dynamically define a class method for such a class:

class Foo end bar = %q{def bar() "bar!" end} Foo.instance_eval(bar) 

But how do you do the opposite: remove / not define a class method? I suspect that the remove_method and undef_method methods can be used for this purpose, but all the examples that I saw after Googling for several hours were to remove / exclude instance methods, not class methods. Or maybe there is syntax that you can pass to instance_eval to do this.

Thanks in advance.

+42
ruby metaprogramming
Jan 16 '10 at 23:00
source share
6 answers
 #!/usr/bin/ruby1.8 class Foo def Foo.bar puts "bar" end end Foo.bar # => bar class <<Foo remove_method :bar end Foo.bar # => undefined method `bar' for Foo:Class (NoMethodError) 

When you define a class method such as Foo.bar, Ruby puts it in the Foo eigenclass. Ruby cannot put it in Foo, because then it will be an instance method. Ruby creates a Foo eigenclass (aka "singleton class"), sets the superclass of the eugenclass class to the Foo superclass, and then sets the Foo superclass to eigenclass:

 Foo -------------> Foo(eigenclass) -------------> Object super def bar super 

This is why we need to open Foo eigenclass using class <<Foo to remove the method panel.

+53
Jan 17 '10 at 0:17
source share

This also works for me (not sure if there are differences between undef and remove_method):

 class Foo end Foo.instance_eval do def color "green" end end Foo.color # => "green" Foo.instance_eval { undef :color } Foo.color # => NoMethodError: undefined method `color' for Foo:Class 
+17
Mar 28 2018-12-12T00:
source share

I think I can’t comment on Adrian’s answer, because I don’t have enough loans, but his answer helped me.

What I found: undef seems to completely remove this method from existence, and remove_method removes it from this class, but it will still be defined on superclasses or other modules that have been extended in this class, etc.

+5
Jun 01 2018-12-12T00:
source share

If you want to delete a method with a name that is being computed dynamically, you should use eigenclasses, for example:

 class Foo def self.bar puts "bar" end end name_of_method_to_remove = :bar eigenclass = class << Foo; self; end eigenclass.class_eval do remove_method name_of_method_to_remove end 

this method is better than other answers, because here I used class_eval with a block. Since now you are blocking the view of the current namespace so that you can use your variables to dynamically delete methods

+3
Oct 17 '13 at 10:01
source share

You can remove a method in two ways. Cutting

 Module#undef_method( ) 

Deletes all methods, including those inherited. More kind

 Module#remove_method( ) 

removes a method from the receiver, but it leaves only inherited methods.

See below 2 simple examples -

Example 1 using undef_method

 class A def x puts "x from A class" end end class B < A def x puts "x from B Class" end undef_method :x end obj = B.new obj.x 

the result is main.rb: 15: in ': undefined method x' for # (NoMethodError)

Example 2 using remove_method

 class A def x puts "x from A class" end end class B < A def x puts "x from B Class" end remove_method :x end obj = B.new obj.x 

Result - $ ruby ​​main.rb

x from class A

+3
Dec 15 '15 at 10:41
source share

Object.send (: remove_const ,: Foo)

-2
Jul 19 '11 at 4:18
source share



All Articles