2011-03-14 66 views
3

以下是處理:我需要使用某些方法擴展具體類的實例。我需要包括模塊內的生活方式,我希望Box實例能夠包括動態模塊。 我現在用一個鉤子與一個eval:將模塊中的方法動態添加到類的特定實例中

class Box 
    def after_initialize 
    if self.injected_module.present? 
     eval("class << self; include #{self.injected_module}; end") 
    end 
    end 
end 

這是合作得非常好,但我真的覺得髒當我使用EVAL。我正在尋找類似的東西:

module_to_inject = self.injected_module 
self.eigenclass.class_eval do 
    include module_to_inject 
end 

但我不能沒有的Monkeypatching類,如能夠得到eigenclass上運行class_eval

class Box; def eigenclass; class << self; self; end end end 

有一個美麗的(和可靠)的方式來做到這一點?

回答

8

所有你需要從模塊添加方法的Box具體情況動態地爲該Kernel#extend方法:

box.extend MyModule 

而且,因爲動詞「注入」已經從Enumerable#inject在Ruby中一個意思,用於描述最好的動詞,這是「延長」。

+0

非常感謝!它像一個魅力一樣工作! – 2011-03-14 12:53:41

3

我無法跟隨你的推理。 self.class.class_eval會工作得很好在你的榜樣,像這樣:

class Box 
    def after_initialize 
    self.class.class_eval do 
     include(self.injected_module) 
    end 
    end 
end 

編輯:澄清意見。

使用Object#extend包括在一個模塊類方法的方法(像在eigenclass會定義它們),像這樣:

module MyModule 
    def method 
     puts "called from #{self.inspect}" 
    end 
end 

class Box 
    def self.injected_module 
     MyModule 
    end 

    def require_module 
     self.class.class_eval do 
      extend self.injected_module 
     end 
    end 
end 

b = Box.new 
b.require_module 
Box.method 
# prints "called from Box" 
+0

這個解決方案的問題是它將一個方法添加到類本身中,而不是放入_eigenclass_中。這樣,如果我在執行此代碼後創建另一個Box實例,該實例將獲得新方法。我正在尋找將方法作爲單例方法包含到我創建的實例中! – 2011-03-14 02:42:28

+0

我無法遵循這個推理。你似乎有「特徵類」的概念困惑。 「eigenclass」是類的同義詞,直接在類上調用的方法,如「Box.method」。然而,在這裏,你將一個Module包含到一個類中,定義了實例方法。你能否試圖澄清你究竟想要什麼? – 2011-03-14 03:12:10

+0

我最好的猜測是你要返回一個單例實例,並希望將一個模塊的方法作爲類方法添加,所以你可以調用'Box.method'而不是調用實例的方法,比如'Box.instance.method' 。您應該使用[Object#extend](http://www.ruby-doc.org/core/classes/Object.html#M001002),而不是使用include。 – 2011-03-14 03:18:00