2011-09-01 153 views
2

這間共享的方法是我的嘗試:如何紅寶石模塊

module A 
    def self.method1; "method1"; end 
    def method2; "method2"; end 
end 

module B; include A; end 

B.method1 # => error 
B.method2 # => error 
B::method1 # => error 
B::method2 # => error 

我想避免複製和粘貼兩個模塊之間的等效代碼。我在這裏使用模塊而不是類的原因是因爲我不需要每個模塊的多個實例,因爲它們只是保存常量(此時爲其他模塊)。

解決此問題的最佳方法是什麼?

+0

如果您只想要此代碼的一個實例,爲什麼不使用單例? –

+0

主要是因爲我不知道該解決方案的優缺點。有些人甚至說他們是邪惡的,而另一些人似乎認爲他們是好的。你怎麼看? – benekastah

+0

正確使用它們可能會有所幫助,但我不確定您的使用情況,所以我無法確定。 –

回答

6

普通include只給你實例方法(method2在你的特定代碼段)。如果你想分享模塊級的方法 - 提取它們與它獨立的模塊和其他extend模塊:

module A 
    extend self  # to be able to use A.method1 

    def method1 
    "method1" 
    end 
end 

module B 
    extend A 
end 

B.method1  # => "method1" 

它也是include可能獲取模塊級的方法,但有一點扭曲,用鉤子方法:

module A 
    def self.included(other) 
    other.extend ModuleMethods # this is where the magic happens 
    end 

    def instance_method 
    'instance method' 
    end 

    module ModuleMethods 
    def module_method 
     'module method' 
    end 
    end 

    extend ModuleMethods  # to be able to use A.module_method 
end 


module B 
    include A 
end 

B.module_method  #=> "module method" 
B.instance_methods  #=> [:instance_method] 
+0

請注意,這不會給你A.method1 - 如果你想這樣做,一個選項將是在A. –

+0

@Greg內調用「擴展自我」這是正確的,好點。 –

1

首先,請注意A.method2也不起作用。您可以創建對象,包括A(或B),將有method2

class C 
    include B # (or A) 
end 
c = C.new 
c.method2 

因此,對於method2它只是工作,你打算。

關於method1,它是對象A的單例方法,無法繼承它。