2016-05-30 65 views
2

我正在閱讀'Metaprogramming Ruby',並同時編寫一些代碼以闡明概念。我已經讀過,當你多次包含/預先安裝一個模塊時,所有進一步的包含都不會改變祖先鏈中所述模塊的位置。Ruby - 包括單個模塊多次和祖先層次結構

我寫了一些代碼,它的工作方式我沒有想到 - 實際發生了什麼?

module GreatGrandfather; end 

module Grandfather 
    include GreatGrandfather 
end 

module Father 
    include Grandfather 
    prepend GreatGrandfather 
end 

module Son 
    include Father 
end 

Son.ancestors # => [Son, Father, Grandfather, GreatGrandfather] 

我認爲當我運行Son.ancestors,兒子將包括父親,父親將包括祖父和曾祖父預先考慮和祖先樹將被設置爲[Son, GreatGrandfather, Father, Grandfather]。顯然這沒有發生。

一旦兒子包括父親,它開始在父模塊中查找並找到include Grandfatherprepend GratGrandfather。它實際上'進入'Grandfather它包括GreatGrandfather,只有然後執行prepend GreatGrandfather線(並忽略它,因爲它已經存在於血統)?

真相被告知,我懷疑我會從中得到多少用處,但不會因爲知道模塊彼此「鏈」的確切程度而受到傷害。

@edit - 我多花了一些時間,而且在任何情況下,我的直覺似乎都沒有錯。我已經包含了我認爲可以實現的兩種方式的圖片,一種是指令後的指令,另一種是關於創建繼承層次的圖片 - 看起來發生在圖片中的那種方式與給出的原始示例背道而馳,所以#1或#2都不能正在發生。

修改的示例代碼(僅曾祖父改變)

module GreatGrandfather 
    include Grandfather 
end 

module Grandfather 
    include GreatGrandfather 
end 

module Father 
    prepend GreatGrandfather 
    include Grandfather 
end 

module Son 
    include Father 
end 

Son.ancestors # => Son, GreatGrandfather, Father, Grandfather 

enter image description here

在總結 - 我仍然不知道是怎麼回事了

回答

1

Module#prepend_feature

Ruby的默認實現覆蓋常量,方法 和這個模塊的模塊變量,如果這個模塊沒有 已經被添加到mod或其祖先之一,則進行mod修改。

但是,您已經通過爺爺添加了GreatGrandfather給父親。

這種方式,你希望它會工作:

module GreatGrandfather; end 

module Grandfather 
    include GreatGrandfather 
end 

module Father 
    prepend GreatGrandfather 
    include Grandfather 
end 

module Son 
    include Father 
end 

p Son.ancestors # => [Son, GreatGrandfather, Father, Grandfather] 

更新

1.You着修改例子是這樣的:

module GreatGrandfather 
    include Grandfather 
end 

module Grandfather 
    include GreatGrandfather 
end 

因爲當你定義曾祖父的祖父沒有定義的。

2.這是,當您將模塊添加到其他模塊時會發生什麼。評論說明,模塊層次結構會發生什麼情況:

module GreatGrandfather 
    # GG 
end 

module Grandfather 
    # GG 
    # G 
    include GreatGrandfather 
    # GG 
    # G -> GG 
end 

module Father 
    # GG 
    # G -> GG 
    # F 
    prepend GreatGrandfather 
    # GG 
    # G -> GG 
    # GG -> F 
    include Grandfather 
    # Don't change the position of GG in Father hierarchy, cause it is already in ancestors 
    # GG 
    # G -> GG 
    # GG -> F -> G 
end 

module Son 
    # GG 
    # G -> GG 
    # GG -> F -> G 
    # S 
    include Father 
    # GG 
    # G -> GG 
    # GG -> F -> G 
    # S -> GG -> F -> G 
end 
+0

謝謝您的回答,雖然說實話它並不十分清楚。我已經添加了一些更多的信息信息 - 你可以稱重嗎? – blob

+0

呵呵,我實際上只是自己弄明白了,因爲我完全忽略了模塊中的代碼立即執行。我一直在玩它,所以我錯過了它抱怨單一化常量 - 如果我把它放在一個文件中,這個問題從一開始就會有明確的答案。謝謝! – blob