我想做以下事情:
我想声明迭代字典的类的实例变量。
我们假设我有这个哈希
hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
我希望将每个键作为类的实例变量。我想知道我是否可以声明迭代遍历该哈希的变量。像这样:
class MyClass
def initialize()
hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
hash.each do |k,v|
@k = v
end
end
end
我知道这不起作用!我只是放了这段代码,看看你能不能理解我想要的更清楚。
谢谢!
答案 0 :(得分:28)
class MyClass
def initialize()
hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
hash.each do |k,v|
instance_variable_set("@#{k}",v)
# if you want accessors:
eigenclass = class<<self; self; end
eigenclass.class_eval do
attr_accessor k
end
end
end
end
eigenclass是一个只属于单个对象的特殊类,因此在那里定义的方法将是该对象的实例方法,但不属于该对象的普通类的其他实例。
答案 1 :(得分:4)
查克的回答比我最近的两次尝试要好。特征类不像我想象的那样self.class
;为了实现这个目标,它花了比我写的更好的测试。
使用我的旧代码,我按以下方式测试,发现该类确实被操作而不是实例:
a = MyClass.new :my_attr => 3
b = MyClass.new :my_other_attr => 4
puts "Common methods between a & b:"
c = (a.public_methods | b.public_methods).select { |v| a.respond_to?(v) && b.respond_to?(v) && !Object.respond_to?(v) }
c.each { |v| puts " #{v}" }
输出结果为:
Common methods between a & b:
my_other_attr=
my_attr
my_attr=
my_other_attr
这显然反驳了我的预设。我很抱歉Chuck,你一直都是。
旧答案:
attr_accessor
仅在类定义中计算时才起作用,而不是在实例的初始化中起作用。因此,直接执行所需操作的唯一方法是将instance_eval
与字符串一起使用:
class MyClass
def initialize(params)
#hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
params.each do |k,v|
instance_variable_set("@#{k}", v)
instance_eval %{
def #{k}
instance_variable_get("@#{k}")
end
def #{k}= (new_val)
instance_variable_set("@#{k}", new_val)
end
}
end
end
end
要测试此尝试:
c = MyClass.new :my_var => 1
puts c.my_var
答案 2 :(得分:4)
class MyClass
def initialize
# define a hash and then
hash.each do |k,v|
# attr_accessor k # optional
instance_variable_set(:"@#{k}", v)
end
end
end
答案 3 :(得分:2)
http://facets.rubyforge.org/apidoc/api/more/classes/OpenStructable.html
OpensStructable是一个mixin模块 这可以提供OpenStruct行为 任何类或对象。 OpenStructable 允许使用扩展数据对象 任意属性。