2011-06-02 128 views

回答

7

我不太明白你的問題。你認爲什麼,在這裏「被阻止」,以及由誰來阻止?

這正是它是如何工作的。 Module#include混合模塊作爲任何類是混入的直接超英寸MFoo父類,因此Foo#bar覆蓋M#bar,因爲這是繼承是如何工作的:子類覆蓋超類,而不是周圍的其他方式。這裏沒有什麼被「阻止」,當然是,你仍然可以在Foo的子類中覆蓋Foo#bar

你可以清楚地看到祖先:

class FooS; end 
module M; end 
class Foo < FooS; include M end 

Foo.ancestors # => [Foo, M, FooS, Object, Kernel, BasicObject] 
+0

啊,我不知道模塊#包括在模塊混合作爲一個直接的超類,它被混入,而不是類本身。我其實還是不明白。因此,如果我有FooS課並且Foo是FooS的子類,那麼您是否說現在將在FooS中定義酒吧?似乎沒有,也沒有任何意義。我一定是誤解你在說什麼。 – farhadf 2011-06-03 00:19:55

+0

@LeftHem:嗯?爲什麼'bar'神奇地被定義在某個地方呢?如果將'FooS'作爲'Foo'的超類添加到混合中,那麼* bar'只有兩個定義,'Foo'和'M'中有一個。爲什麼其中一個會突然跳來跳去? 'M' * still *被插入爲'Foo'的直接超類(因此顯​​然,作爲'FooS'的子類)並且'Foo#bar' *的定義仍然*覆蓋了M#bar的定義',因爲'Foo' *仍然是'M'的一個子類。在Foo上面插入一個超類沒有任何改變,畢竟之前有一個超類:Object。 – 2011-06-03 00:27:43

+0

我的不好 - 「作爲一個直接的超級」,而不是「直接的超級」。現在我懂了。 – farhadf 2011-06-03 00:45:25

-1

你包括呼叫不會做你認爲...嘗試Foo.send(:extend,M)

+0

我的理解是,延長補充方法爲類方法。沒有?將最後兩行替換爲Foo.methods.grep(/bar/).inspect Foo.send(:extend,M) Foo.new.bar puts Foo.methods.grep(/bar/).inspect 你會發現它已被添加到課程中。不知道爲什麼這個評論系統不允許回車 – farhadf 2011-06-03 00:05:14

+0

在這個問題上,我還是不明白,我認爲這是問題的核心;這應該工作,如果你把包括在課堂...... – DGM 2011-06-03 00:05:35

5

改寫@約爾格的回答是:

如果你

Foo.send(:include,M) 
Foo.ancestors 

你回來

[Foo, M, Object, Kernel, BasicObject] 

這意味着,當bar被調用,它看起來是否有Foo#bar第一,並且只有當它不存在時它纔會嘗試查看M#bar(然後Object,Kernel,BasicObject,然後調用method_missing)。

就個人而言,我不介意在查看Foo之前先查看M的能力。我聽說有添加到Ruby 2.0這樣做的能力說話,但是這不會幫助您現在。

+2

我想'Module#prepend'(這就是你所說的)實際上已經在YARV trunk中實現了。與其他一些東西(尤其是精化)不同,它是完全沒有爭議的,而且很容易實現,所以它實際上最終保證了Ruby 2.0規範。事實上,向後兼容,我不會驚訝地發現它在1.9.3中(如果甚至有一個)。 – 2011-06-03 01:53:42

+0

@Jorg:爲什麼不會有1.9.3?他們是否想過直接進入2.0? – 2011-06-03 02:28:03

+0

'x = Foo.new; x.extend M; x.bar'將覆蓋該方法,模塊的方法中的'super'將調用實例方法。詳情:http://subinterest.com/rubies-in-the-rough/15-learn-to-love-mix-ins – 2012-05-22 17:33:01

相關問題