Ruby扩展&包括跟踪代码

时间:2018-04-20 01:26:23

标签: ruby-on-rails ruby include extend

我对使用“include”vs“extend”感到困惑,在搜索了几个小时后,我得到的是模块方法与类的实例一起使用,包括模块,以及类扩展时类本身使用的模块方法这些方法的模块。

但这并没有帮助我弄清楚,为什么这段代码在“#extend Inventoryable”中评论扩展模块行时会出错 取消注释时工作,这是代码

module Inventoryable

    def create(attributes)
      object = new(attributes)
      instances.push(object)
      return object
    end

    def instances
      @instances ||= []
    end

  def stock_count
    @stock_count ||= 0
  end

  def stock_count=(number)
    @stock_count = number
  end

  def in_stock?
    stock_count > 0
  end
end

class Shirt
  #extend Inventoryable
  include Inventoryable
  attr_accessor :attributes

  def initialize(attributes)
    @attributes = attributes
  end
end

 shirt1 = Shirt.create(name: "MTF", size: "L")
 shirt2 = Shirt.create(name: "MTF", size: "M")
 puts Shirt.instances.inspect

输出

store2.rb:52:in `<main>': undefined method `create' for Shirt:Class (NoMethodError)

当取消注释“extend Inventoryable”以使代码工作时:

module Inventoryable

    def create(attributes)
      object = new(attributes)
      instances.push(object)
      return object
    end

    def instances
      @instances ||= []
    end

  def stock_count
    @stock_count ||= 0
  end

  def stock_count=(number)
    @stock_count = number
  end

  def in_stock?
    stock_count > 0
  end
end

class Shirt
  extend Inventoryable
  include Inventoryable
  attr_accessor :attributes

  def initialize(attributes)
    @attributes = attributes
  end
end

 shirt1 = Shirt.create(name: "MTF", size: "L")
 shirt2 = Shirt.create(name: "MTF", size: "M")
 puts Shirt.instances.inspect

使代码工作并输出以下内容

[#<Shirt:0x0055792cb93890 @attributes={:name=>"MTF", :size=>"L"}>, #<Shirt:0x0055792cb937a0 @attributes={:name=>"MTF", :size=>"M"}>] 

它有点令人困惑,但我需要知道的是,为什么我需要扩展模块以避免错误?以及如何编辑此代码以使其在没有extend方法的情况下工作? ,代码中还剩下哪些依赖于扩展?

3 个答案:

答案 0 :(得分:4)

当你extend一个模块时,该模块中的方法变为&#34;类方法&#34; **。因此,当您extend Inventoryable时,create可用作Shirt类的方法。

当你include一个模块时,该模块中的方法变为&#34;实例方法&#34; **。因此,当您include Inventoryable时,create类上没有Shirt,但<{1}}的实例上 可用。)

要在使用Shirt时在create课程中提供Shirt,您可以使用include挂钩。这可能看起来像:

included

然后,如果你这样做:

module Inventoryable
  module ClassMethods

    def create
      puts "create!"
    end

  end

  module InstanceMethods

  end

  def self.included(receiver)
    receiver.extend ClassMethods
    receiver.include InstanceMethods
  end
end

你可以这样做:

class Shirt
  include Invetoryable
end

**人群中的红宝石纯粹主义者会正确地指出,在ruby中,一切都是实例方法,并且没有类方法。这正式100%正确,但我们在这里使用> Shirt.create create! => nil class方法的口语含义。

答案 1 :(得分:1)

当你在一个类中扩展一个模块时,你将模块的方法暴露为类方法,但如果你包含模块,那么你将模块的方法作为实例方法,在你的例子中,你可以调用{{1您需要使用create类的实例调用Inventoryable类的方法(如果包含模块)

Shirt

如果没有更多信息,我无法确定您要尝试做什么,但您需要重新设计shirt1 = Shirt.new(attributes).create(attributes) initialize方法,以确定在这些方法中的位置或操作。

我将尝试使用一个简单的例子来解释它

create

希望它有所帮助。

答案 2 :(得分:1)

在一天结束时,它非常简单:

  • C.include(M)使C的超类MM的超类成为C的超类。换句话说,它会将M插入C的祖先链。
  • obj.extend(M)(大致)与obj.singleton_class.include(M)相同。