我想用class_eval來擴展某些類的功能。我想強制這個類繼承一些其他類的一些方法。Metaprogramming Ruby:在class_eval中定義繼承
即:
SomeClass.class_eval do
# force inheritence from some other class
end
什麼是實現這一目標的最佳途徑?
我想用class_eval來擴展某些類的功能。我想強制這個類繼承一些其他類的一些方法。Metaprogramming Ruby:在class_eval中定義繼承
即:
SomeClass.class_eval do
# force inheritence from some other class
end
什麼是實現這一目標的最佳途徑?
如果重寫現有的功能,是這裏的硬性要求,你需要有這也是包含在一個模塊中定義的那些現有的方法。
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
嘗試使用include
和extend
,兩者均解釋爲here。他們只使用模塊;你只需要不能在Ruby創建完成後修改/添加Ruby類的超類。
只有一個問題:你不能覆蓋在這個主題的第三點意見的解釋一類已有的方法。
而且更多信息請參見this話題。
我怎麼會去的情況時,我已經有一個類,想什麼是外部模塊定義來覆蓋它的方法的? – alexs333 2012-04-04 03:37:18
更新帖子... – Jwosty 2012-04-04 03:56:25
模塊將不會實際工作來覆蓋類本身指定的功能,因爲紅寶石回溯在繼承層次結構找到方法,幷包括一個方法只是插入該模塊到直接類以上的層次結構。班級本身仍然是第一個被檢查的地方。 ...雖然我仍然同意Jwosty這是解決這個問題的正確方法。如果您確實需要覆蓋已經在該類上定義的方法,則可以通過在自己的模塊上定義它們來解決此問題。 – Burke 2012-04-04 04:14:40
當我試圖重載的類方法坐在一些第三方引擎代碼中,我不能重構成模塊... :(否則你的解決方案工作... – alexs333 2012-04-04 04:37:25
好了,然後更新解決方案,這只是一點點更復雜 – Burke 2012-04-04 04:43:16
爲什麼你需要使用class_eval?您可以直接將方法定義轉儲到class_eval中,或者如果您希望替換方法位於其他位置,則可以構建一個模塊,在定義替換之前刪除現有方法。 – Burke 2012-04-04 04:49:29