我寫在Ruby的內部DSL。爲此,我需要以編程方式創建命名類和嵌套類。最好的辦法是什麼?我偵察,有兩種方法可以做到這一點:動態定義命名的類在Ruby中
- 使用
Class.new
創建一個匿名類,然後使用define_method
的方法添加到它,最後調用const_set
將其添加爲命名常量一些命名空間。 - 使用某種
eval
我測試過的第一種方式,它的工作,但作爲新的Ruby,我不知道該把類作爲常量纔是正道。
是否有其他更好的方法?如果不是,上述哪一項更可取?
我寫在Ruby的內部DSL。爲此,我需要以編程方式創建命名類和嵌套類。最好的辦法是什麼?我偵察,有兩種方法可以做到這一點:動態定義命名的類在Ruby中
Class.new
創建一個匿名類,然後使用define_method
的方法添加到它,最後調用const_set
將其添加爲命名常量一些命名空間。eval
我測試過的第一種方式,它的工作,但作爲新的Ruby,我不知道該把類作爲常量纔是正道。
是否有其他更好的方法?如果不是,上述哪一項更可取?
如果你想創建一個具有動態名稱的類,你將不得不做幾乎完全你所說的。但是,您不需要使用define_method
。您只需將一個塊傳遞給Class.new
即可在其中初始化該類。這在語義上與class
/end
的內容相同。
記住與const_set
,以勤勞在該範圍的接收器(self
)的。如果您希望全局定義該類,則需要在TopLevel模塊上調用const_set
(它在Ruby中的名稱和細節上有所不同)。
a_new_class = Class.new(Object) do
attr_accessor :x
def initialize(x)
print #{self.class} initialized with #{x}"
@x = x
end
end
SomeModule.const_set("ClassName", a_new_class)
c = ClassName.new(10)
...
我還應該提到,類名固有地是常量。它們被定義爲它們包含的模塊的常量。 –
您可以更具體地瞭解頂級模塊的名稱嗎? –
你並不真的需要使用const_set
。的Class.new
返回值可以被分配給一個 常數和Class.new
塊是class_eval
。
class Ancestor; end
SomeClass = Class.new(Ancestor) do
def initialize(var)
print "#{self.class} initialized with #{var}"
end
end
=> SomeClass
SomeClass.new("foo")
# SomeClass initialized with foo=> #<SomeClass:0x668b68>
這不創建一個類具有動態名稱。 SomeClass是靜態確定的。 –
不是。當這個類被用於某些事物時,常量名將被刪除。在你的例子中https://gist.github.com/1064909 – Julik
,你正在將你的新類定義爲「SomeClass」。你剛剛粘貼的例子與你的陳述相矛盾:「你並不需要使用const_set」。您確實需要使用它來將某些東西綁定到模塊常量。 –
應該是這樣
a_new_class = Class.new(Object) do
attr_accessor :x
def initialize(x)
@x = x
end
end
SomeModule = Module.new
SomeModule.const_set("ClassName", a_new_class)
c = SomeModule::ClassName.new(10)
'eval'是最好避免。 http://stackoverflow.com/questions/637421/is-eval-supposed-to-be-nasty –