簡體   English   中英

使用Class vs Module在Ruby中打包代碼

[英]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 你的問題的假設是你不想實例化任何東西,所以我建議你只使用一個模塊。

仍然你應該重新考慮你的方法:不是使用數組或你正在做的任何代表矩陣的數組,而是讓你自己的類來表示矩陣,或找到別人已經寫過的好類更優雅。

在您的兩個示例中,您實際上並未在ClassModule定義方法; 你是在一個恰好是ClassModule的對象上定義單例方法,但可能只是關於任何對象。 這是一個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中,類是一種模塊。

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

以下也有效

Matrix = Object.new

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

那是因為所謂的“類方法”只是添加到單個對象的方法,而對象類的含義並不重要。

作為形式,模塊更正確。 您仍然可以創建類的實例,即使它只有類方法。 您可以將此處的模塊視為C#或Java的靜態類。 類也始終具有與實例相關的方法( newallocate等)。 使用模塊。 類方法通常與對象有關(創建它們,操縱它們)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM