Ruby mixin - 访问类实例中的模块实例变量

时间:2017-05-26 12:47:34

标签: ruby mixins

我对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未初始化。 另外一点是,我不能使用&#39; +&#39; action_1方法中的运算符。 我错过了什么?

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

1 个答案:

答案 0 :(得分:2)

实例变量属于实例(这就是为什么它们被称为&#34;实例变量&#34;)。这里有三个感兴趣的对象,每个对象都有自己的@b,它与其他对象的任何其他@b无关:ModuleA有自己的对象@bModuleB一样,instA也有自己的@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