2015-08-14 29 views
2

我有這個模塊:爲什麼`Object.include`和`Fixnum.prepend`的順序很重要?

module MyMod 
    def +(other) 
    puts "hello" 
    end 
end 

這個成功覆蓋+Fixnum

Fixnum.prepend(MyMod) 

123 + :test # outputs "hello" 

比方說,我需要的+運營商覆蓋了Fixnum和其他對象。這成功地將覆蓋+Fixnum和其他對象:

Fixnum.prepend(MyMod) 
Object.include(MyMod) 

123 + :test # outputs "hello" 

但是,如果我改變prependinclude的順序,我的覆蓋沒有影響:

Object.include(MyMod) 
Fixnum.prepend(MyMod) 

123 + :test # error: -:10:in `+': :test can't be coerced into Fixnum (TypeError) 

爲什麼的include順序和prepend這裏有這個效果嗎?

+0

哦,順便說一句,這是我用它爲:https://gist.github.com/henrik/36b991205d6c772b5a1f#file-pipeline1-rb –

回答

4

Module#prepend_features文檔:

當在該模塊中的另一個被預置,Ruby調用prepend_features在此模塊中,向它傳遞所述接收模塊在國防部。如果這個模塊還沒有被添加到Mod或其祖先的某個祖先中,Ruby的默認實現是將這個模塊的常量,方法和模塊變量覆蓋到mod 。另請參見Module#prepend。

所以,如果它的參數還沒有被添加到接收器或其祖先之一prepend僅做任何事情。由於ObjectFixnum的始祖,Fixnum.prepend(MyMod)Object.include(MyMod)之後調用時什麼也不做。

+0

哦,這麼簡單。非常感謝你! SO會讓我接受你的答案。 –

+0

Andrian回答了您的問題(+1),但爲什麼急於選擇一個答案,以及爲什麼承諾選擇一個特定的答案時,其他人(而不是我)毫無疑問正在解答?快速選擇可能會阻礙其他答案,如果不是更好的話,仍然可以提供有趣的觀察結果。 –

+0

@CarySwoveland我發表了這樣的聲明,所以Adrian不用擔心我不知道接受答案,因爲在超時之前我無法接受答案。我接受答案的「政策」是接受第一個回答我的問題的答案 - 如果稍後有更好的答案,我很樂意提出答案(我做到了)。即使它不是第一個答案,是否通常會提出最詳細的答案? –

4

只是爲了澄清@阿德里安的答案。

祖先鏈無改裝:

puts Fixnum.ancestors 
# >> Fixnum 
# >> Integer 
# >> Numeric 
# >> Comparable 
# >> Object 
# >> Kernel 
# >> BasicObject 

隨着 「工作」 改裝

Fixnum.prepend(MyMod) 
Object.include(MyMod) 

puts Fixnum.ancestors 
# >> MyMod # here it is, having precedence over Fixnum#+ 
# >> Fixnum 
# >> Integer 
# >> Numeric 
# >> Comparable 
# >> Object 
# >> MyMod # note the second copy. include(MyMod) doesn't check for duplicates, but it doesn't matter (here). 
# >> Kernel 
# >> BasicObject 

以 「不工作」 的改裝

Object.include(MyMod) 
Fixnum.prepend(MyMod) 

puts Fixnum.ancestors 
# >> Fixnum 
# >> Integer 
# >> Numeric 
# >> Comparable 
# >> Object 
# >> MyMod # fixnum will override this 
# >> Kernel 
# >> BasicObject 
+0

謝謝你,塞爾吉奧!這使得事情更加清晰。 –

相關問題