簡體   English   中英

self.included - 包括Ruby中模塊的類方法

[英]self.included – including class methods from a module in Ruby

我讀過這篇文章: Ruby模塊 - 包括do end block - 但是當你在模塊中使用self.included do ... end塊時仍然無法獲得。

帖子說當你包含模塊時,塊中的代碼將被運行,但是如果要包含模塊的唯一目的,那么它的重點是什么? 這個代碼不需要運行嗎? 該塊不需要存在就可以運行該代碼,對吧?

下面兩者之間有什么區別:

module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

module M
  def self.some_class_method
     ...
  end

  scope :disabled, -> { where(disabled: true) }
end

這兩個例子有什么區別?

第一個代碼塊將ClassMethods的類方法ClassMethods到包含類,並在其上調用scope方法。 第二個沒有做這些事情並且會導致NoMethodError因為模塊沒有scope類方法。 包含模塊后, self.some_class_method將不會在包含類中提供。

有關模塊包含如何在Ruby中工作的完整故事,請在此處閱讀我的答案:
從Ruby中的modules / mixins繼承類方法

什么是點self.included如果要包含一個模塊的唯一目的是什么?

包含不是模塊的唯一目的。 它們還用於其他事物,例如命名空間或簡單地存儲可在模塊本身上調用的各種類方法。

為什么Ruby不自動包含類方法?

從理論上講,Ruby 可以自動將模塊中定義的所有類方法添加到包含類中,但實際上這是一個壞主意,因為您不再需要選擇是否要包含類方法 - 所有類方法都將包含在每個方法中時間,無論是否打算包括在內。 考慮這個例子:

module M
  def self.class_method
    "foo"
  end

  def self.configure_module
    # add configuration for this module
  end
end

class C
  include M
end

這里, configure_module方法顯然不應該添加到C ,因為它的目的是設置模塊對象的配置。 然而,如果我們有類方法的自動包含,你將無法阻止它被包括在內。

但是所有實例方法都已包含在內! 那怎么樣呢?

模塊中的實例方法只有在包含在類中才真正有用 ,因為模塊不能有實例,只有類可以。 因此,在一個模塊中,每個實例方法都應該被包含在某個地方工作。

模塊上的“類”方法是不同的,因為它可以在模塊本身上調用,因此無論它是否也添加到包含類,它都可以正常使用。 這就是為什么你有一個選擇更好的原因。

module M
  # self.included is the hook which automatically runs when this module is included
  def self.included(base)
    puts 'this will be printed when this module will be included inside a class'
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  def print_object_class
    self.class.name # here self will be the object of class which includes this module
  end

  module ClassMethods
    def print_class_name
      self.name # Here self would be the class which is including this module
    end
  end
end

我嘗試修改上面的module以幫助您了解模塊(關注點)如何在代碼可重用性方面發揮作用

self.included是一個鈎子,當一個模塊包含在一個類中時它會自動運行。

module ClassMethods聲明的任何方法module ClassMethods都將成為包含此模塊的類的類方法

module ClassMethods外部聲明的任何方法module ClassMethods將成為包含此模塊的類的實例方法

對於Ex,假設有一個Product類,並且您已將模塊包含在其中

class Product < ActiveRecord::Base
  include M
  puts 'after including M'
end

如果您在rails控制台中嘗試此示例,您會注意到,只要模塊M包含在class Product包含的模塊運行掛鈎中,

this will be printed when this module will be included inside a class打印在控制台上this will be printed when this module will be included inside a class將打印出來

after including M之后,這將被打印在控制台上。

您也可以嘗試以下命令

Product.disabled # a scope with name 'disabled' is avaialble because of including the module M
Product.print_class_name # Outputs => 'Product' This method is available to class with the help of module M
Product.new.print_object_class #Outputs => 'Product'

它還提供可重用性,在任何類中包含此模塊M,並且該類可以訪問模塊中描述的所有這些方法。

而你的第二個例子僅僅是基本模塊的一個例子

module N
  def self.abc
    puts 'basic module'
  end
end

現在只能使用此模塊訪問模塊中的abc方法定義

N.abc # outputs 'basic module'

class Product < ActiveRecord::Base
  include  N
end

Product.abc #raises異常,沒有在類Product.new.abc #raises異常上找到的方法,沒有找到類對象的方法

我希望這可以幫助您更好地理解模塊的概念。 如果您還有任何疑問,請告訴我。

暫無
暫無

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

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