2012-04-04 25 views

回答

1

如果重寫現有的功能,是這裏的硬性要求,你需要有這也是包含在一個模塊中定義的那些現有的方法。

class SomeClass 
    include DefaultBehaviour 
end 

module DefaultBehaviour 
    def run 
    puts "ran default" 
    end 
end 

module AlternateBehaviour 
    def run 
    puts "ran alternate" 
    end 
end 

SomeClass.class_eval { 
    include AlternateBehaviour 
} 

SomeClass.new.run #=> "ran alternate" 

原因是因爲ruby的方法查找路徑。

它從SomeClass - > Object開始。

當你包括AlternateBehaviour,它成爲SomeClass的 - > AlternateBehaviour - >對象。所以直接在SomeClass上定義的方法仍然優先。但是,如果在DefaultBehaviour上定義了這些方法,則查找路徑將變爲SomeClass - > AlternateBehaviour - > DefaultBehaviour - > Object,因此您的替代方法將優先。無論哪個模塊最近被列入最高優先級。

在你沒有原始類的控制的情況下,你可以做,而不是:

module AlternateBehaviour 
    def self.included(base) 
    base.send(:remove_method, :run) 
    end 

    def run 
    puts "ran alternate" 
    end 
end 

雖然在這一點上,人們開始懷疑是否可能通過只是在做

更好
SomeClass.class_eval { 
    def run 
    "ran alternate" 
    end 
end 
+0

當我試圖重載的類方法坐在一些第三方引擎代碼中,我不能重構成模塊... :(否則你的解決方案工作... – alexs333 2012-04-04 04:37:25

+0

好了,然後更新解決方案,這只是一點點更復雜 – Burke 2012-04-04 04:43:16

+0

爲什麼你需要使用class_eval?您可以直接將方法定義轉儲到class_eval中,或者如果您希望替換方法位於其他位置,則可以構建一個模塊,在定義替換之前刪除現有方法。 – Burke 2012-04-04 04:49:29

0

嘗試使用includeextend,兩者均解釋爲here。他們只使用模塊;你只需要不能在Ruby創建完成後修改/添加Ruby類的超類。

只有一個問題:你不能覆蓋在這個主題的第三點意見的解釋一類已有的方法。

而且更多信息請參見this話題。

+0

我怎麼會去的情況時,我已經有一個類,想什麼是外部模塊定義來覆蓋它的方法的? – alexs333 2012-04-04 03:37:18

+0

更新帖子... – Jwosty 2012-04-04 03:56:25

+0

模塊將不會實際工作來覆蓋類本身指定的功能,因爲紅寶石回溯在繼承層次結構找到方法,幷包括一個方法只是插入該模塊到直接類以上的層次結構。班級本身仍然是第一個被檢查的地方。 ...雖然我仍然同意Jwosty這是解決這個問題的正確方法。如果您確實需要覆蓋已經在該類上定義的方法,則可以通過在自己的模塊上定義它們來解決此問題。 – Burke 2012-04-04 04:14:40