[英]Using Class vs Module for packaging code in Ruby
假設我有一堆沒有持久狀態的相關函數,比如字符串差異包中的各種操作。 我可以在類或模塊中定義它們(使用self
),它們可以以完全相同的方式訪問:
class Diff
def self.diff ...
def self.patch ...
end
要么
module Diff
def self.diff ...
def self.patch ...
end
然后我可以做Diff.patch(...)
。 哪個'更好'(或'正確')?
我需要將它們分組的主要原因是命名空間問題,常用的函數名稱都在其他地方使用。
編輯:將示例從矩陣更改為差異。 Matrix是一個可怕的例子,因為它確實有狀態,每個人都開始解釋為什么把它們作為方法而不是回答實際問題更好。 :(
模塊和類之間的主要區別在於您無法實例化模塊; 你不能做obj = MyModule.new
。 你的問題的假設是你不想實例化任何東西,所以我建議你只使用一個模塊。
仍然你應該重新考慮你的方法:不是使用數組或你正在做的任何代表矩陣的數組,而是讓你自己的類來表示矩陣,或找到別人已經寫過的好類更優雅。
在您的兩個示例中,您實際上並未在Class
或Module
定義方法; 你是在一個恰好是Class
或Module
的對象上定義單例方法,但可能只是關於任何對象。 這是一個String
的例子:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
您可以執行其中的任何操作,但這樣可以將相關方法分組的最佳方法是在Module
作為普通實例方法(即沒有self.
):
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
line,它可以調用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.foo
也會發生同樣的事情, foo
將無法用於包括它的任何類。 簡而言之,只有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
Ruby模塊用於指定行為,相關功能。
Ruby Classes用於指定狀態和行為,一個單一的實體。
軟件設計中有一個格言,即代碼是一種負擔,因此盡可能使用較少的代碼。 在Ruby的情況下,代碼行的差異是cero。 所以你可以使用任何一種方式(如果你不需要保存狀態)
如果您想成為純粹主義者,請使用模塊,因為您不會使用狀態功能。 但我不會說使用類是錯誤的。
作為一個瑣事信息:在Ruby中,類是一種模塊。
以下也有效
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
那是因為所謂的“類方法”只是添加到單個對象的方法,而對象類的含義並不重要。
作為形式,模塊更正確。 您仍然可以創建類的實例,即使它只有類方法。 您可以將此處的模塊視為C#或Java的靜態類。 類也始終具有與實例相關的方法( new
, allocate
等)。 使用模塊。 類方法通常與對象有關(創建它們,操縱它們)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.