2013-11-05 52 views
2

我想設置一些Ruby代碼,以便我可以動態地定義一個新的類。我現在的代碼如下所示,我認爲它會工作,但它不工作,我有點困惑爲什麼不。Ruby元編程 - 通過proc動態定義一個新類。

def define_new_class(&block) 
    new_class = Class.new(MyClass) do 
    yield 
    end 
end 

define_new_class do 
    attr_accessor :my_accessor_1 

    def initialize 
    puts "Hello" 
    end 
end 

任何有識之士將不勝感激!

回答

3

你很近,但有幾件事情。首先,Class.new的參數定義了新類的超類,但MyClass未定義。其次,你真的想評價您所定義,而不是僅僅產生於該塊類的範圍內的塊 - 因此instance_eval

def define_new_class(&block) 
    new_class = Class.new do 
    self.instance_eval &block 
    end 
end 

a = define_new_class do 
    attr_accessor :my_accessor_1 

    def initialize 
    puts "Hello" 
    end 
end 

我的猜測是,你首先必須MyClass的原因是,你想要的結果類是可引用爲MyClass如果是這樣的話,你可以不喜歡

Object.const_set('MyClass', a) 

因此,在一個大的快樂方法:

def define_new_class(name, &block) 
    new_class = Class.new do 
    self.instance_eval &block 
    end 
    Object.const_set(name, new_class) 
end 

define_new_class('MyClass') do 
    attr_accessor :my_accessor_1 

    def initialize 
    puts "Hello" 
    end 
end 

a = MyClass.new #=> #<MyClass:0x007f8baaaf72c8> 
a.my_accessor_1 = 1 #=> 1 
a.my_accessor_1 # => 1 
+0

我只是使用MyClass作爲佔位符 - 它是在別處定義的。我在代碼的不同部分設置常量。我會試一試你的'instance_eval'解決方案! – Bryce

+0

亞歷克斯,我想知道哪裏可以使用'模塊#const_set'。這在這方面很有幫助。一件小事:我認爲你不需要用'self.'來引用'instance_eval'。我注意到'self.'通常被添加到不需要的地方。這在某種程度上是文體偏好嗎? –

+0

對我來說,絕對是一種文體選擇。只是想讓它在評估區塊的情況下變得非常清楚。我聽說過你應該主要將'自我'限制在屬性設置者身上,但我傾向於更頻繁地拋棄它。 –