2015-08-14 75 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

谢谢你,塞尔吉奥!这使得事情更加清晰。 –

相关问题