2010-11-02 62 views
9

在Ruby中,有没有办法动态地添加一个实例变量到一个类?例如:动态创建类属性与attr_accessor

class MyClass 

    def initialize 
    create_attribute("name") 
    end 

    def create_attribute(name) 
    attr_accessor name.to_sym 
    end 

end 

o = MyClass.new 
o.name = "Bob" 
o.name 
+2

你知道'OpenStruct'? – Reactormonk 2010-11-02 22:44:05

回答

25

的方法之一(还有其他人)是使用instance_variable_setinstance_variable_get像这样:

class Test 
    def create_method(name, &block) 
     self.class.send(:define_method, name, &block) 
    end 

    def create_attr(name) 
     create_method("#{name}=".to_sym) { |val| 
      instance_variable_set("@" + name, val) 
     } 

     create_method(name.to_sym) { 
      instance_variable_get("@" + name) 
     } 
    end 
end 

t = Test.new 
t.create_attr("bob") 
t.bob = "hello" 
puts t.bob 
+1

我喜欢你的解决方案,它是干净的节目getter和setter。谢谢! – dhulihan 2010-11-03 17:59:59

+1

你怎么会去把这个变成一个模块,使您可以在与您希望此功能的类混? – ericso 2012-08-22 00:19:17

1

也许,

instance_variable_set(name,value) 

是什么你想!

如:

class Mclass 
    def show_variables 
    puts self.class.instance_variables 
    end 
end 

Mclass.instance_variable_set(:@test,1) 
o=Mclass.new 
o.show_variables 
你知道

,类是对象了。

0

制造回答@ ericso的评论/问题的另一条评论,所以这里的一个烂摊子它是在一个答案 - 我使用一个模块(基于@ ReeseMoore的代码)要做到这一点&集实例瓦尔,如果必要的话:

# adds ability to dynamically create instance vars & attr_accessors 
module Attributable 
    def create_method(name, &block) 
    self.class.send(:define_method, name.to_sym, &block) 
    end 

    def create_setter(m) 
    create_method("#{m}=".to_sym) { |v| instance_variable_set("@#{m}", v) } 
    end 

    def create_getter(m) 
    create_method(m.to_sym) { instance_variable_get("@#{m}") } 
    end 

    def set_attr(method, value) 
    create_setter method 
    send "#{method}=".to_sym, value 
    create_getter method 
    end 
end