2015-11-21 161 views
8

我試圖更好地理解模塊如何擴展和包含對方。Ruby:模塊擴展/包括模塊

說我有模塊一個

module A 
    def learned_from_A 
    true 
    end 
end 

A.instance_methods # [:learned_from_A] 

我的錦囊混入

module B 
    extend A 
end 

B.learned_from_A # true 

我天真地試圖給ç一切已:

module C 
    extend B 
end 

C.learned_from_A # NoMethodError 

我想我已經把我的頭包裹在裏面了。

B.singleton_methods # [:learned_from_A] 

雖然::當延伸,的A的實例方法的拷貝經由B的單個類勢必 learned_from_A可調用,這不是B的一個實例方法,所以當ç延伸:learned_from_A不是複製到C


如果不得不代替包括一個,的的實例方法副本會一直被列入B的自己的實例方法之一。

module B 
    include A 
end 

B.instance_methods # [:learned_from_A] 

然後,Ç可以,並且所有的B的實例方法(包括:learned_from_A)延伸將被複制並綁定到Ç

module C 
    extend B 
end 

C.singleton_methods # [:learned_from_A] 

爲了使:learned_from_A可調用二者B關於Ç可以延伸包括

module B 
    include A 
    extend A 
end 

B.instance_methods # [:learned_from_A] 
B.singleton_methods # [:learned_from_A] 

module C 
    extend B 
end 

C.instance_methods # [] 
C.singleton_methods # [:learned_from_A] 

更爲現實的,如果我想一個的方法可以被調用於,併爲定義自己的另一種方法能夠混合整個劇目爲ç,我不能做到這一點:

module B 
    extend A 
    include A 

    def self.buzz 
    true 
    end 
end 

module C 
    extend B 
end 

B只能共享其實例方法,而不是其單例方法。因此,爲了使兩者在可贖回和可共享到其他對象的方法,它必須被定義爲實例方法,並擴展到本身:

module B 
    extend A 
    include A 

    extend self 

    def buzz 
    true 
    end 
end 

module C 
    extend B 
end 

有試驗了相當數量的並把這一切放在一起的錯誤。這是一種查看正在發生的事情的準確方法嗎?

+0

有什麼方法可以簡化您的問題嗎?即使你將它放在調試出的不同場景的要點上。 – onebree

+0

我想你可能會混淆自我的範圍變化,當你在B裏面擴展A,然後期待C會有A.你可以改變範圍。還有#prepend可以被調用。 要查看這些範圍如何變化,請在您的班級上調用$ ancestors方法。 –

+1

聽起來像你想打電話給媽媽和女兒同名:P –

回答

2

我混的錦囊分爲B

這句話和你一般的問題讓我相信這是在include/extend事情的概念有點誤會。我提前道歉,因爲我沒有完全理解這個問題。

例如,你有這樣的模塊:

module A 
    def a 
    puts "a" 
    end 

    def self.b 
    puts "b" 
    end 
end 

正如所看到的,有兩種類型的方法:

  • singleton_methods
  • instance_methods

這是最簡單的方式來表明他們實際上不同:

A.singleton_methods 
=> [:b] 
A.instance_methods 
=> [:a] 
A.a 
NoMethodError: undefined method `a' for A:Module 
A.b 
b 
=> nil 

如果你簡單地include A要添加其例如方法,當前模塊實例方法。當您簡單地執行extend A時,您正在將其方法實例添加到當前模塊單例方法中。

​​

還有一兩件事要說的是,你可以extend self但不include self爲不使任何意義,也將引發異常。

module D 
    extend self 

    def a 
    puts "a" 
    end 

    def self.b 
    puts "b" 
    end 
end 

D.singleton_methods 
=> [:b, :a] 
D.instance_methods 
=> [:a] 
D.a 
a #no error there because we have such singleton method 
=> nil 

我想這些東西可以幫助你。關於您可能檢查的StackOverflow上的extend/include有很多問題(example)。

+1

很好的答案!我想,有一點意外轉換。上面的一個陳述應該是:「當你簡單地擴展A時,你正在將它的**實例**方法添加到當前模塊** singleton **方法中。」 (*「instance」*和「* singleton *」被替換爲答案) – ivan

+0

@ivan謝謝,好點。 –