2013-05-13 67 views
5

新手問題:我可以從同一模塊添加類方法和實例方法嗎?

我知道如何包括和擴展工作,我想知道的是,如果有一種方法可以從單個模塊獲取類和實例方法嗎?

這是我如何與兩個模塊做到這一點:

module InstanceMethods 
    def mod1 
     "mod1" 
    end 
end 

module ClassMethods 
    def mod2 
     "mod2" 
    end 
end 

class Testing 
    include InstanceMethods 
    extend ClassMethods 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 

感謝你的時間......

回答

9

有一個共同的成語說。它利用included對象模型鉤子。每次將模塊包含到模塊/類中時,都會調用此鉤子

module MyExtensions 
    def self.included(base) 
    # base is our target class. Invoke `extend` on it and pass nested module with class methods. 
    base.extend ClassMethods 
    end 

    def mod1 
    "mod1" 
    end 

    module ClassMethods 
    def mod2 
     "mod2" 
    end 
    end 
end 

class Testing 
    include MyExtensions 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 
# >> mod1 
# >> mod2 

我個人喜歡將實例方法組合到一個嵌套模塊中。據我所知,這是不太被人接受的做法。

module MyExtensions 
    def self.included(base) 
    base.extend ClassMethods 
    base.include(InstanceMethods) 

    # or this, if you have an old ruby and the line above doesn't work 
    # base.send :include, InstanceMethods 
    end 

    module InstanceMethods 
    def mod1 
     "mod1" 
    end 
    end 

    module ClassMethods 
    def mod2 
     "mod2" 
    end 
    end 
end 
+0

感謝您清除了這一點給我。清除描述性信息。非常感謝您花時間。 – 2013-05-13 15:23:30

+0

請參閱我的答案,對此進行相當簡潔的簡化。 :) – Magne 2017-11-27 11:53:26

2
module Foo 
def self.included(m) 
    def m.show1 
    p "hi" 
    end 
end 

def show2 
    p "hello" 

end 
end 

class Bar 
include Foo 
end 

Bar.new.show2 #=> "hello" 
Bar.show1 #=> "hi" 
+0

感謝您抽出時間,塞爾吉奧在第一時間得到了接受的答案。 – 2013-05-13 15:27:49

0

是。這是你所期望的完全一樣簡單,由於紅寶石的天才:

module Methods 
    def mod 
     "mod" 
    end 
end 

class Testing 
    include Methods # will add mod as an instance method 
    extend Methods # will add mod as a class method 
end 

t = Testing.new 
puts t.mod 
puts Testing::mod 

或者,你可以這樣做:

module Methods 
    def mod1 
     "mod1" 
    end 

    def mod2 
     "mod2" 
    end 
end 

class Testing 
    include Methods # will add both mod1 and mod2 as instance methods 
    extend Methods # will add both mod1 and mod2 as class methods 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 
# But then you'd also get 
puts t.mod2 
puts Testing::mod1 
+0

如果你需要像'self.included'這樣的鉤子,那麼你也可以使用'self.extended'。見https://www.sitepoint.com/hitchhikers-guide-to-metaprogramming-classmodule-hooks/ – Magne 2017-11-27 11:55:05

+0

我不認爲你理解這個問題。 :)想象一下,一個模塊/關注點攜帶兩組預期的方法:一個成爲實例方法,另一個 - 類[實例]方法。問題是:如何從同一模塊添加兩個(不同的!)方法集。 – 2017-11-27 11:59:49

+0

我的確認識到這是解釋它的一種方法。但是tbh,這個問題並不清楚需要兩個不同的方法集(即使他現有的示例代碼是必需的)。它的優點在於,一個模塊對於如何使用它是不可知的。您不必預測模塊中的方法將如何使用。但是,如果模塊中有多個方法,並且執行了包含和擴展,那麼您將擁有所有可用的實例方法和類方法(非獨特)。 – Magne 2017-11-27 12:35:42

相關問題