2012-08-10 41 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類

相關問題