假设我有两个模块:
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
同样,@a
在类中的实例方法中是nil
。我觉得我不理解这里重要的事情。我想了解为什么我所做的不起作用,以及实现我所需功能的正确方法是什么。
答案 0 :(得分: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
答案 1 :(得分: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