2013-07-03 13 views
5

Giả sử tôi có hai mô-đun:của Ruby mô-đun năng động mix-in

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 

Bây giờ, tôi muốn có điều kiện trộn các phân hệ vào một lớp. Đây là những gì tôi đã cố gắng:

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 

Đây là hành vi tôi nhìn thấy:

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

Cũng @anil trong các phương pháp dụ trong lớp. Tôi cảm thấy rằng tôi không hiểu điều gì đó quan trọng ở đây. Tôi muốn hiểu lý do tại sao những gì tôi đang làm không hoạt động và cách thức chính xác để đạt được chức năng mong muốn của tôi là gì.

Trả lời

9

Bạn có hành vi này bởi vì các biến mẫu bạn đặt trong mô-đun này thuộc về các mô-đun thay vì thuộc về các trường hợp MyClass. Hãy xem xét mã này:

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

Để giải quyết vấn đề này, bạn có thể sử dụng extend thay vì 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 

Và trong lớp học của bạn:

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

Tuyệt vời, đây chính xác là những gì tôi đang tìm kiếm. Cảm ơn! –

2

tôi nghĩ ra một cách để làm việc xung quanh vấn đề này, vì vậy tôi nghĩ rằng tôi muốn chia sẻ nó. Tôi vẫn muốn xem liệu có ai biết cách nào tốt hơn để đạt được những gì tôi đang cố gắng không.

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 
Các vấn đề liên quan