如何在Ruby中通过变量实例化对象?

时间:2014-09-27 22:23:26

标签: ruby metaprogramming

class Foo
end

class_name = 'Foo'
f = eval(class_name).new
#<Foo:0x007fd3e273ed68>

此示例创建Foo的预期实例。

期望定义该类,但我们想要实例化class_name中定义的类的对象。

class_name的值来自用户,因此上面的代码是一个非常糟糕的想法...

3 个答案:

答案 0 :(得分:2)

查看Module::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

答案 1 :(得分:1)

const_get可以获得对Class

的引用
Module.const_get( :Foo ).new

Module.const_get( 'Foo' ).new

注意:在&lt; 1.9它只搜索当前模块。

答案 2 :(得分:1)

一堂课没什么特别的。它只是一个分配给变量的对象,或者在您显示的代码的情况下,是一个常量。因此,您可以使用相同的元编程方法从变量中检索类,就像使用任何其他对象一样:Object#instance_variable_getModule#class_variable_getBinding#local_variable_getThread#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>

请注意,其他两个答案中的代码只会偶然发生:它们会在Foo类的上下文中查找Module,这只会有效,因为您实际上 Foo中定义的ObjectModule的{​​{1}}继承自Object。如果您已将Foo定义为不在祖先中,而是在Module的兄弟中,那么其他两个答案中的代码将不起作用:

module Bar; class Foo; end end

Module.const_get(:Foo)
# NameError: uninitialized constant Module::Foo

Bar.const_get(:Foo)
# => Bar::Foo

如果你希望const_get的行为与普通的常量查找相同,你需要在想要实际查找它的类/模块上调用它,而不是在一些随机类中。