2013-07-03 31 views
5

假設我有兩個模塊:紅寶石動態模塊的混合式

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。我覺得我不瞭解這裏重要的東西。我想了解爲什麼我正在做的工作不正常,以及實現我想要的功能的正確方法是什麼。

回答

9

您有此行爲,因爲您在模塊中設置的這些實例變量屬於模塊本身,而不屬於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 
+0

完美,這正是我一直在尋找的。謝謝! –

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