class Foo
end
class_name = 'Foo'
f = eval(class_name).new
#<Foo:0x007fd3e273ed68>
本示例创建Foo的预期实例。如何在Ruby中通过变量实例化对象?
该类预计会被定义,但我们想要实例化一个在class_name
中定义的类的对象。
为class_name
值来自用户的,所以上面的代码是一个非常糟糕的主意™ ...
class Foo
end
class_name = 'Foo'
f = eval(class_name).new
#<Foo:0x007fd3e273ed68>
本示例创建Foo的预期实例。如何在Ruby中通过变量实例化对象?
该类预计会被定义,但我们想要实例化一个在class_name
中定义的类的对象。
为class_name
值来自用户的,所以上面的代码是一个非常糟糕的主意™ ...
一个类没什么特别的。它只是一个分配给变量的对象,或者在你显示的代码中是一个常量。所以,你可以使用相同的元编程的方法来从一个变量检索类,你会与任何其他对象使用:Object#instance_variable_get
,Module#class_variable_get
,Binding#local_variable_get
,Thread#thread_variable_get
,或者其中一个是适用于这种情况Module#const_get
:
class Foo; end
class_name = 'Foo'
foo = Object.const_get(class_name).new
#=> #<Foo:0x007fd3e273ed68>
foo = self.class.const_get(class_name).new
#=> #<Foo:0x007fd3e273ed68>
注意,在其他两个答案的代码只能小心:他们在Module
类,因为你有实际上在Object
和Module
继承Object
定义Foo
只适用的情况下查找Foo
。如果你没有在祖先但在Module
同级定义Foo
,然后在其他两个答案的代码是行不通的:
module Bar; class Foo; end end
Module.const_get(:Foo)
# NameError: uninitialized constant Module::Foo
Bar.const_get(:Foo)
# => Bar::Foo
如果你想const_get
的运行方式正常常量查找同样会,你需要在你想要真正查看它的类/模块上调用它,而不是在某个随机类上。
class Foo
end
class_name = 'Foo'
myClass = Module.const_get(class_name)
myClass.new
当然,顾名思义,你可以用它来获得任何形式的常数。所以,可能是明智的检查,如果你得到一个类回:
SOME_CONST = 5
Module.const_get('SOME_CONST').is_a? Class # => false
Module.const_get('String').is_a? Class # => true
哇,这是我正在寻找的答案。谢谢。你有什么资源可以推荐用于Metaprogramming? – 2014-09-28 12:06:18
Ruby程序员不倾向于将元编程看作任何特殊的东西。这对他们来说只是正常编程的一个自然部分,所以他们通常也不会考虑为它编写特殊资源。用于Ruby编程的任何资源也将涵盖元编程,即使在最开始时也是如此:'attr_accessor'是一种生成方法的方法,每次使用'attr_accessor'时,都会执行元编程。然而,如果你可以放纵自己独特的风格,那么[为什么这个幸运儿](https://wikipedia.org/wiki/Why_the_lucky_stiff)的作品,在解释元编程方面非常擅长。 – 2014-09-28 13:14:51
例如,请参阅[*为什么(Poignant)Ruby指南](http://mislav.uniqpath.com/poignant-guide/),特别是[* Dwemthy's Array *](http://mislav.uniqpath。com/poignant-guide/dwemthy /)(一个使用Ruby元编程的地下城游戏!)另外,总是有Paolo Perrotta的[*元程序Ruby *](https://pragprog.com/book/ppmetr2/metaprogramming-ruby -2)。但是,我不能说任何这些资源,因为我自己实际上是通过Ruby编程来学习Ruby Metaprogramming的,因为这很自然。 – 2014-09-28 13:18:43