Ruby 中有没有办法将符号或字符串转换为同名的类?
例如,如果我有一个类,如
class Bob
def talk
puts "Hi, I'm bob"
end
end
我在代码中其他地方的方法传递了一个符号:bob,我可以以某种方式将它变成类 Bob 吗?也许像
b = :Bob.new
b.talk
或者有没有办法做类似的事情?
有很多方法可以做到这一点。您缺乏上下文使得无法选择“最佳”方式。这里有几个。
Kernel.const_get(:Bob)
eval(:Bob.to_s)
Kernel.const_get(:bob.to_s.capitalize)
仅用于 Rails。
用一个字符串:
"Module".constantize #=> Module
"Class".constantize #=> Class
带符号:
:module.to_s.classify.constantize #=> Module
:open_struct.to_s.classify.constantize #=> OpenStruct
如果您正在处理多字符号,那么您需要添加#classify
到链中以正确处理常量所有部分的大写。
http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize
如果你想把 :foo_bar 变成 FooBar,我见过的解决方案都没有。如果这就是你要找的东西:
:foo_bar.to_s.split("_").collect(&:capitalize).join.constantize
=> FooBar
希望对某人有所帮助。
NameSpace.const_get(classname)
将返回类对象(假设 classname 包含类的名称 - 如果它包含不是类的常量的名称,它将返回该常量的值)。顶层命名空间是 Object,所以你可以这样做Object.const_get(:Bob).new
class Bob
end
def create(name)
return eval("#{name}.new")
end
b = create(:Bob)
puts b.class
这是我在寻找包含模块/命名空间支持的类似内容时想到的:
['foo', 'bar'].inject {|r,e| "#{r.classify}::#{e.classify}"}.constantize
生产
=> Foo::Bar
然而,这需要 Rails,当然它只适用于数组包含多个元素的情况。
这看起来很简单,所以我确定我错过了一些东西,有人愿意告诉我为什么这不是一个好方法吗?
谢谢!
就我而言,下面的两个示例都有效,但您也不必忘记命名空间:
Object.const_get("ModuleName::#{class_model_name}")
或者
Kernel.const_get("ModuleName::#{class_model_name}").