2011-12-13 27 views
2

假設我有一堆沒有持久狀態的相關函數,比如字符串差異包中的各種操作。我可以在一個類或模塊(使用self)定義了他們,他們可以訪問完全相同的方式:使用類與模塊在Ruby中打包代碼

class Diff 
    def self.diff ... 
    def self.patch ... 
end 

module Diff 
    def self.diff ... 
    def self.patch ... 
end 

我可以再做Diff.patch(...)。哪個「更好」(或「正確」)?

我需要將它們組合起來的主要原因是命名空間問題,常用函數名稱都在別的地方使用。

編輯:將矩陣變爲例子。矩陣是一個可怕的例子,因爲它確實有狀態,每個人都開始解釋爲什麼最好把它們寫成方法而不是回答實際問題。 :(

回答

3

在你的兩個例子中,你實際上並沒有在ClassModule中定義方法;你在一個對象上定義單例方法,這個方法碰巧是一個Class或者一個Module,但是可以是任何對象。下面是一個String一個例子:

Diff = "Use me to access really cool methods" 

def Diff.patch 
    # ... 
end 

你可以做這些,這將工作,但將相關的方法,最好的方法是在一個Module正常實例方法(不self. IE):

module Diff 
    extend self # This makes the instance methods available to the Diff module itself 
    def diff ... # no self. 
    def patch ... 
end 

現在,您可以:

  • 使用任何類中(與include Diff)此功能或任何對象(extend Diff
  • 此用途的一個示例是extend self系列,可以調用Diff.patch
  • 即使在全局命名空間

例如使用這些方法,在irb

class Foo 
    include Diff 
end 
Foo.new.patch # => calls the patch method 
Diff.patch # => also calls Diff.patch 
include Diff # => now you can call methods directly: 
patch   # => also calls the patch method 

:在extend self將 「修改」 的Diff模塊對象本身,但它不會對模塊的內含物有任何影響。同樣的事情發生在def self.foofoo將不可用於包括它的任何類。簡而言之,只有Diff的實例方法通過include(或extend)導入,而不是單例方法。只有繼承一個類將提供實例和單例方法的繼承。

當你真的想要包含一個模塊來提供實例方法和單例方法時,這並不是一件容易的事情。你必須使用self.included鉤:

module Foo 
    def some_instance_method; end 

    module ClassMethods 
    def some_singleton_method; end 
    end 

    def self.included(base) 
    base.send :extend, ClassMethods 
    end 

    def self.will_not_be_included_in_any_way; end 
end 

class Bar 
    include Foo 
end 
# Bar has now instance methods: 
Bar.new.some_instance_method # => nil 
# and singleton methods: 
Bar.some_singleton_method # => nil 
2

紅寶石模塊用於指定行爲,相關功能件。

的Ruby類是用來同時指定狀態和行爲,單個的實體。

有一個在軟件設計格言說代碼是一個責任,所以儘量少使用代碼,在Ruby的情況下,代碼行的差異是cero,所以你可以使用任何一種方式(如果你不需要保存狀態)

如果你想成爲一個純粹主義者,然後使用一個模塊,因爲你不會使用狀態功能。但是我不會說使用一個類是錯了。

作爲一個瑣事信息:在Ruby中,類是一種模塊。

http://www.ruby-doc.org/core-1.9.3/Class.html

+0

@alexloh我改變了答案 – Nerian 2011-12-13 23:44:02

+0

感謝。我將會使用Module,因爲這似乎是很酷的孩子們所做的事情。 – alexloh 2011-12-14 22:53:08

1

下也適用

Matrix = Object.new 

def Matrix.add ... 
def Matrix.equals ... 

這是因爲所謂的「類方法」只是添加到單個對象的方法,它並不真正的問題是對象類是什麼。

3

模塊和類的主要區別是你不能實例化一個模塊;你不能這樣做obj = MyModule.new。你的問題的假設是你不想實例化任何東西,所以我建議只使用一個模塊。

你應該重新考慮一下你的方法:而不是使用數組或者你正在做的任何事情來表示一個矩陣,那麼讓你自己的類表示一個矩陣或者find a good class that someone else has already written會更加優雅。

1

就形式而言,模塊更爲正確。您仍然可以創建類的實例,即使它只有類方法。您可以將模塊視爲C#或Java的靜態類。類也總是有實例相關的方法(newallocate等)。使用模塊。類方法通常與對象有關(創建它們,操作它們)。