Ruby mixin - 在 class 个实例中访问模​​块实例变量

Ruby mixin - accessing module instance variables in class instances

我是 Ruby 的新手,似乎我仍然对 类 中的 mixin 和包含模块感到困惑。我希望能够访问 类 中模块中定义的实例变量 (@)。 我有以下代码:

module ModuleB
  attr_reader :b

  def ModuleB.initialize(browser)
    puts "initialize from ModuleB"
    @browser = browser
    @b = 5
  end
end

module ModuleA
  attr_reader :a
  include ModuleB

  def ModuleA.initialize(browser)
    ModuleB.initialize(browser)
    puts "initialize from ModuleA"
    @browser = browser
    @a = @b
  end

  def action_1
    @a = @b + 1
    return @a
  end
end

class ClassA
  include ModuleA
  def initialize(browser)
    ModuleA.initialize(browser)
    @browser = browser
    puts 'initialize - method in ClassA'
    @c = @a
    @d = @b
    puts "a = #{@a}"
    puts "b = #{@b}"
    puts "c = #{@c}"
    puts "d = #{@d}"
  end

end

s = 'hello'
instA = ClassA.new(s)
puts instA.action_1

这是我得到的输出:

initialize from ModuleB
initialize from ModuleA
initialize - method in ClassA
a =
b =
c =
d =
mixin_example2.rb:23:in `action_1': undefined method `+' for nil:NilClass (NoMethodError)
        from mixin_example2.rb:46:in `<main>'

似乎 @a@b 未初始化。 另外,我不能在 action_1 方法中使用“+”运算符。 我错过了什么?

抱歉,如果我重复了可能已经提出的问题,但到目前为止我还没有找到答案。

实例变量属于实例(这就是它们被称为"instance variables"的原因)。您在这里有三个感兴趣的对象,每个对象都有自己的 @b,与其他对象的任何其他 @b 无关:ModuleA 有自己的@bModuleBinstA 也有自己的 @b

以下是您尝试执行的更明智的实施方式:

module ModuleB
  def initialize(browser)
    puts "initialize from ModuleB"
    @browser = browser
    @b = 5
  end
end

module ModuleA
  include ModuleB

  def initialize(browser)
    super
    puts "initialize from ModuleA"
    @a = @b
  end

  def action_1
    @a = @b + 1
  end
end

class ClassA
  include ModuleA

  def initialize(browser)
    super
    puts 'initialize - method in ClassA'
    @c = @a
    @d = @b
    puts "a = #@a"
    puts "b = #@b"
    puts "c = #@c"
    puts "d = #@d"
  end
end

s = 'hello'
instA = ClassA.new(s)
# initialize from ModuleB
# initialize from ModuleA
# initialize - method in ClassA
# a = 5
# b = 5
# c = 5
# d = 5
#=> #<ClassA:0x007f8b5f12e110 @a=5, @b=5, @browser="hello", @c=5, @d=5>

puts instA.action_1
# 6