6

假设我有两个模块:

module Test1

  attr_accessor :a, :b

  @a = 0.0
  @b = 0.0

end

module Test2

  attr_accessor :c, :d

  @c = 0.0
  @d = 0.0

end

现在,我想有条件地将这些模块混合到一个类中。这是我尝试过的:

require './Test1.rb'
require './Test2.rb'

class MyClass

  def initialize(mode)
    if mode == 0
      (class << self; include Test1; end)
    elsif mode == 1
      (class << self; include Test2; end)
    else
      class << self
        include Test1
        include Test2
      end
    end
  end

end

这是我看到的行为:

obj = MyClass.new(0)
obj.a  #=> nil

也是类@anil的实例方法。我觉得我在这里没有理解重要的东西。我想了解为什么我正在做的事情不起作用,以及实现我想要的功能的正确方法是什么。

4

2 回答 2

11

您有这种行为是因为您在模块中设置的这些实例变量属于模块本身而不是属于MyClass实例。考虑这段代码:

Test1.instance_variable_get(:@a)
# => 0.0

要解决此问题,您可以使用extend代替include

module Test1

  attr_accessor :a, :b

  def self.extended(object)
    object.a, object.b = 0.0, 0.0
  end

end

module Test2

  attr_accessor :c, :d

  def self.extended(object)
    object.c, object.d = 0.0, 0.0
  end

end

在你的课堂上:

require './Test1.rb'
require './Test2.rb'

class MyClass

  def initialize(mode)
    if mode == 0
      extend Test1
    elsif mode == 1
      extend Test2
    else
      extend Test1
      extend Test2
    end
  end

end
于 2013-07-03T14:20:40.143 回答
2

我想到了一种解决这个问题的方法,所以我想我会分享它。我仍然想看看是否有人知道更好的方法来实现我的目标。

Module Test1
  attr_accessor :a, :b

  def init1
    @a = 0.0
    @b = 0.0
  end
end

class MyClass
  def initialize
    if mode == 0
      (class << self; include Test1; end)
      init1
    elsif mode == 1
      ...
  end
end
于 2013-07-03T14:40:10.920 回答