2012-08-10 56 views
14

我想重新定义一个方法,但避免与之相关的警告。我应该使用undef_method还是remove_method来做到这一点?何时使用undef_method以及何时使用remove_method?

(是,重新定义方法是有点哈克。我这样做是因为我有一些记忆化,我希望在单元测试正在运行使用,而不是程序本身在运行时。)

回答

20

fine manual

undef_method(符号)→自

从响应来电来命名的方法防止当前类。将此与remove_method对比,该方法从特定类中删除该方法; Ruby仍然会为可能的接收器搜索超类和混合模块。

所以一个remove_method这样的:

class CC < C 
    remove_method :m 
end 

本质上是这样的相反:

class CC < C 
    def m 
    end 
end 

def m添加方法m到类,remove_method :m去除m。但是,如果超类具有m方法,那么仍将使用该方法。

undef_method,OTOH,更是这样的:

class CC < C 
    def m 
     raise 'No, you cannot do that.' 
    end 
end 

所以undef_method实际上并没有删除方法,它会替换该方法以使Ruby的一个特殊的内部标志抱怨,如果你试图调用方法。

听起来你试图取代现有的方法和更换是语义相同的删除后跟添加所以remove_method可能是比较合适的。但是,如果你想成为偏执狂,并确保替换方法到位,那么undef_method将是有用的;或者,如果由于某种原因需要在一个地方删除该方法并将其添加到另一个地方,那么undef_method至少会告诉您,您只完成了一半的工作,而remove_method将使您获得超类的实现(并且可能存在奇怪的错误)或者相当令人困惑的NoMethodError

+0

真棒解释。 – 2014-07-15 11:46:35

4

您可以通过两种简单的方法删除一个方法。剧烈

Module#undef_method() 

删除所有方法,包括继承的方法。金德

Module#remove_method() 

去除接收器的方法,但它 叶独自继承的方法。

见下2简单例子 - main.rb的 - 使用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 

结果

实施例1: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 

结果 - $红宝石main.rb的

X从A类

相关问题