2015-11-01 147 views
3

我想動態創建一組類,如下所示。 Ruby:動態創建新類

class Foo 
    attr_reader :description 
end 

['Alpha', 'Beta', 'Gamma'].each do |i| 
    klass = Class.new(Foo) do |i| 
    def initialize 
     @description = i 
    end 
    end 
    Object.const_set(i, klass) 
end 

而不是手動創建每個類, g .:

class Alpha < Foo 
    def initialize 
    @description = 'Alpha' 
    end 
end 

什麼是正確的方式來做這樣的事情,以及如何將迭代器傳遞到嵌套塊?

回答

1

我如何通過一個迭代器嵌套塊?

通過使用嵌套。 def不是一個塊。 def會切斷def之外的變量的可見性。在另一方面,一個可以看到塊外的變量:

class Foo 
    attr_reader :description 
end 

['Alpha', 'Beta', 'Gamma'].each do |class_name| 
    klass = Class.new(Foo) do 
    define_method(:initialize) do 
     @description = class_name 
    end 
    end 

    Object.const_set(class_name, klass) 
end 

a = Alpha.new 
p a.description 

--output:-- 
"Alpha" 

你也可以做你想做的,而無需創建一個嵌套的塊或類Foo:

['Alpha', 'Beta', 'Gamma'].each do |class_name| 
    klass = Class.new() do 
    def initialize 
     @description = self.class.name 
    end 

    attr_reader :description 

    end 

    Object.const_set(class_name, klass) 
end 

--output:-- 
"Alpha" 
"Gamma" 
+0

'@description = self.class.name'可以使用或不使用父類。這是一個很好的解決方案! – mwp

1

你很近。我想你想讓description成爲一個類實例變量(或可能是一個類變量),而不是一個實例變量。對於Alpha類的所有對象,description將爲「Alpha」,因此它應該是該類的一個屬性。您可以將其作爲Alpha.description(或Alpha.new.class.description)訪問。下面是使用一個類的實例變量的解決方案:

class Foo 
    class << self 
    attr_reader :description 
    end 
end 

['Alpha', 'Beta', 'Gamma'].each do |i| 
    klass = Class.new(Foo) 
    klass.instance_variable_set(:@description, i) 

    Object.const_set(i, klass) 
end 
+0

偉大的答案+1 – illusionist

+0

*對於Alpha類的所有對象,描述將是「Alpha」,因此它應該是該類的一個屬性。* - 不一定...因爲對類實例*變量的更改將影響所有實例看到的內容。另一方面,如果變量是在'initialize()'內部創建的,那麼每個實例都有自己的變量,並且可以獨立於其他實例進行更改。 – 7stud

+0

確實如此,但我們將描述設置爲類的名稱,所以如果這是OP要執行的斷言,則對於該類的所有實例而言,這將是相同的。如果OP希望能夠靈活地將實例的描述設置爲稍後的其他內容,那麼是的,您的方法效果更好。 – mwp

1
class Foo 
    attr_reader :description 
end 

['Alpha', 'Beta', 'Gamma'].each do |class_name| 
    eval %Q{ 
    class #{class_name} < Foo 
     def initialize 
     @description = #{class_name} 
     end 
    end 
    } 
end 

在執行:

Gamma.new.description 
=> Gamma