通过包含模块的方法访问实例变量

时间:2017-09-18 20:26:00

标签: ruby module instance-variables memoization

示例代码和输出可以在这里找到:

module A
  def self.included(base)
    base.include InMethods
  end

  module InMethods
    def mem
      @mem ||= []
    end

    def add(n)
      mem += n
    end
  end
end

class Help
  include A
end

h = Help.new
h.add(1)
# in `add': undefined method `+' for nil:NilClass (NoMethodError)

基本上,我包含一个包含子模块的模块,但真正的问题在于方法和实例变量。这对我来说是一种常见的模式,但由于我试图从我所包含的模块中做到这一点,我遇到了麻烦。

1 个答案:

答案 0 :(得分:2)

这实际上与模块/包含/继承/无关。你在常规课程中得到同样的错误。

class Help
  def mem
    @mem ||= 0
  end

  def add(n)
    mem += n
  end
end

Help.new.add(1)
# test.rb:16:in `add': undefined method `+' for nil:NilClass (NoMethodError)

当你使用语法糖mem +=时,Ruby实际上将其扩展为mem = mem +。第一个问题是这是从左到右解释的,因此mem =定义了一个掩盖方法的局部变量mem。那么第二个mem引用一个已定义但未设置的局部变量,你得到nil

第二个问题是你没有定义一个setter mem=方法,所以它根本不能改变@mem

要解决这两个问题,你可以做到

attr_writer :mem

def add(n)
  self.mem += n
end