2014-03-14 111 views
1

道歉的標題,建議使其更清晰,歡迎。Ruby - 從包含另一個模塊的模塊獲取類和實例方法?

我創建了一個模塊(我們將用M表示),當included在類中時,將導致它獲得新的類方法和實例方法(如果我的術語不正確,請諒解)。這通過以下代碼中的F類包括A::ModuleInstanceMethods模塊來實現。

現在,我已經做了,我想創建一個新的模塊(我們稱這個新的模塊M'),它包括了模塊M,這樣當M'包含在一個班,每班應獲得根據類F的適當類和實例方法。這是我卡住的地方。在下面的代碼中,這樣的類的示例是G

我還希望include模塊M''(模塊M''將包括M')具有相同的功能。下面的代碼將是一個示例H。包括M'''(其本身包括M''),類別M''''(其本身包括M''')的類別也應該如此,等等。這與繼承層次非常相似。

如果我的文字說明很混亂,請閱讀下面的代碼。特別是,我想解決致電G.class_method_oneH.class_method_one造成的故障,但我缺乏這方面的知識。

我知道在我感興趣的類中只有extendA::ModuleClassMethods模塊是可能的,但我希望避免這樣做。通過在A::ModuleInstanceMethods中用base.instance_of? Class手動添加部分self.included函數也可以實現同樣的效果,但如果可能的話,我想以編程方式進行,而不是在許多不同的站點中複製和粘貼相同的代碼。

module A 
    module ModuleClassMethods 
    def class_method_one 
     2 
    end 
    end 

    module ModuleInstanceMethods 
    def instance_method_one 
     3 
    end 

    def self.included(base) 
     if base.instance_of? Class 
     base.extend(A::ModuleClassMethods) 
     elsif base.instance_of? Module 
     # Intended functionality: 
     # When modules that `include` A::ModuleInstanceMethods are themselves 
     # included in a class (such as module `A::D` included in class `F`), 
     # class `F` will get the functions defined in the A::ModuleClassMethods 
     # module as class level methods 
     end 
    end 
    end 

    module D 
    include A::ModuleInstanceMethods 
    end 

    module E 
    include D 
    end 
end 

class F 
    include A::ModuleInstanceMethods 
end 

class G 
    include A::D 
end 

class H 
    include A::E 
end 

F.class_method_one # 2 
F.new.instance_method_one # 3 

G.new.instance_method_one # 3 
# below statement fails 
# G.class_method_one 

H.new.instance_method_one # 3 
# below statement fails 
# H.class_method_one 

謝謝。

+1

'我希望避免使用extend'。爲什麼?聽起來像是解決問題最簡單,最乾淨的方法。 –

+0

'extend'是解決問題的最簡單方法。我正要說,直到我看到你對我的答案發表評論時,這可能不是最乾淨的方式。我認爲你是對的。 – yanhan

回答

0

我似乎已經想通了。該解決方案使用module_eval。對於module s,它添加​​了self.included函數,它調用A::ModuleInstanceMethods.included。我不介意學習更優雅的解決方案。

module A 
    module ModuleClassMethods 
    def class_method_one 
     2 
    end 
    end 

    module ModuleInstanceMethods 
    def instance_method_one 
     3 
    end 

    def self.included(base) 
     if base.instance_of? Class 
     base.extend(A::ModuleClassMethods) 
     elsif base.instance_of? Module 
     base.module_eval { 
      def self.included(base) 
      A::ModuleInstanceMethods.included(base) 
      end 
     } 
     end 
    end 
    end 
end 
+1

這可能並可能會導致問題。你的模塊的用戶可能想要定義他自己的「included」鉤子。你的任何一個都會覆蓋用戶的,否則用戶會覆蓋你的。人們可以繞過這一切,但我想知道是否有更好的方法。另外,請看['Object#define_singleton_method'](http://ruby-doc.org/core-2.1.1/Object.html#method-i-define_singleton_method)。 –

+0

你有一個很好的觀點;我沒有想到這一點。 +1 – yanhan

相關問題