您可以动态定义类的类方法,如下所示:
class Foo
end
bar = %q{def bar() "bar!" end}
Foo.instance_eval(bar)
但是你如何做相反的事情: 删除/取消定义 一个类方法?我怀疑Module的remove_method
和undef_method
方法可以用于此目的,但是我在谷歌搜索几个小时之后看到的所有示例都是用于删除/取消定义实例方法,而不是类方法。或者也许有一种语法可以传递给instance_eval
来执行此操作。
提前致谢。
答案 0 :(得分:61)
#!/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)
当你定义像Foo.bar这样的类方法时,Ruby会把它放到Foo的本征类中。 Ruby不能把它放在Foo中,因为那样它就是一个实例方法。 Ruby创建了Foo的本征类(又名“单例类”),将本征类的超类设置为Foo的超类,然后将Foo的超类设置为本征类:
Foo -------------> Foo(eigenclass) -------------> Object
super def bar super
这就是为什么我们必须使用class <<Foo
打开Foo的本征类来删除方法栏。
答案 1 :(得分:18)
这对我也有用(不确定undef和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
答案 2 :(得分:6)
我想我无法评论阿德里安的回答,因为我没有足够的信誉,但他的回答对我有帮助。
我发现:undef
似乎完全删除了该方法,而remove_method
将该类从该类中删除,但它仍将在超类或其他已扩展的模块上定义上课等。
答案 3 :(得分:4)
您可以通过两种简单的方法删除方法。激烈的
Module#undef_method( )
删除所有方法,包括继承的方法。更友善
Module#remove_method( )
从接收器中删除该方法,但它 留下遗传方法。
见下面的2个简单例子 -
示例1使用 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
结果 -
main.rb:15:
': undefined method
x'代表#(NoMethodError)
示例2使用 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
结果 - $ ruby main.rb
来自A类
答案 4 :(得分:3)
如果您想删除名称为dinamically计算的方法,您应该使用如下的特征类:
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
这种方式比其他人的答案更好,因为我在这里使用了class_eval和block。正如您现在阻止查看当前命名空间,因此您可以使用您的变量来删除方法
答案 5 :(得分:-2)
Object.send(:remove_const,:Foo)