2009-10-23 34 views
14

我想要做以下事情:聲明迭代散列的實例變量!

我想聲明迭代字典的類的實例變量。

讓我們假設我有這個哈希

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 

我知道這是行不通的!我只把這段代碼看看能否更清楚地理解我想要的東西。

謝謝!

回答

27
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只是屬於單個對象的特殊類,所以定義的方法會出現該對象的實例方法,但不屬於該對象的正常類的其他實例。

+5

查克,你忘了@字母的前綴... – 2009-10-23 18:36:11

+3

現在我沒有。 – Chuck 2009-10-23 18:45:45

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 
+1

'self.class'不是**特徵類。修改'self.class'會影響屬於該類的每個對象,而修改對象的特徵類只會影響該對象。在某些情況下它們是可以互換的,但通常不會。 – Chuck 2009-10-25 07:01:14

+0

從1.8.7開始,我測試了一下,發現你的斷言是錯誤的。儘管如此,這是我測試的唯一版本。 – 2009-10-26 00:33:28

+0

然後你的測試是有缺陷的。運行這個:'「Hello」.class.class_eval {def size()9000 end};放置「Bye」.size',你會看到覆蓋「Hello」.class中的方法也會影響完全不相關的字符串「Bye」的行爲。在任何可能遇到的Ruby版本中都是如此。 – Chuck 2009-10-27 00:18:58

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 
+0

感謝您的可選評論!但哈希迭代器中的attr_accessor塊不工作... 我該怎麼做? (創建attr_accessors迭代) – flyer88 2009-10-23 19:07:11

+0

爲了執行'attr_accessor',您需要位於類上下文中。獲取實例的類上下文的方法是使用對象的本徵類,就像我的答案中一樣。 – Chuck 2009-10-23 20:27:58