如何检查一个类是否已定义?
如何将字符串转换为类名,但前提是该类已经存在?
如果 Amber 已经是一个类,我可以通过以下方式从字符串获取该类:
Object.const_get("Amber")
或 (在 Rails 中)
"Amber".constantize
但是,如果以下情况中的任何一个都将失败,并显示 NameError: uninitializedconstant Amber
Amber 还不是一个类。
我的第一个想法是使用 define?
方法,但它不会区分已经存在的类和不存在的类:
>> defined?("Object".constantize)
=> "method"
>> defined?("AClassNameThatCouldNotPossiblyExist".constantize)
=> "method"
那么,在我尝试之前,如何测试字符串是否命名了一个类转换它? (好吧,用 begin
/rescue
块来捕获 NameError 错误怎么样?太丑了?我同意......)
How do I turn a string into a class name, but only if that class already exists?
If Amber is already a class, I can get from a string to the class via:
Object.const_get("Amber")
or (in Rails)
"Amber".constantize
But either of these will fail with NameError: uninitialized constant Amber
if Amber is not already a class.
My first thought is to use the defined?
method, but it doesn't discriminate between classes that already exist and those that don't:
>> defined?("Object".constantize)
=> "method"
>> defined?("AClassNameThatCouldNotPossiblyExist".constantize)
=> "method"
So how do I test if a string names a class before I try to convert it? (Okay, how about a begin
/rescue
block to catch NameError errors? Too ugly? I agree...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
const_define 怎么样?
?请记住,在 Rails 中,开发模式下会自动加载,因此在测试时可能会很棘手:
How about
const_defined?
?Remember in Rails, there is auto-loading in development mode, so it can be tricky when you are testing it out:
在 Rails 中,这非常简单:
In rails it's really easy:
受到@ctcherry 上面的响应的启发,这里有一个“安全类方法发送”,其中
class_name
是一个字符串。如果class_name
没有命名类,则返回nil。一个更安全的版本,仅当
class_name
响应时才调用method
:Inspired by @ctcherry's response above, here's a 'safe class method send', where
class_name
is a string. Ifclass_name
doesn't name a class, it returns nil.An even safer version which invokes
method
only ifclass_name
responds to it:看来使用
Object.const_define?
方法的所有答案都是有缺陷的。如果由于延迟加载而尚未加载相关类,则断言将失败。明确实现这一目标的唯一方法如下:It would appear that all the answers using the
Object.const_defined?
method are flawed. If the class in question has not been loaded yet, due to lazy loading, then the assertion will fail. The only way to achieve this definitively is like so:我创建了一个验证器来测试字符串是否是有效的类名(或以逗号分隔的有效类名列表):
I've created a validator to test if a string is a valid class name (or comma-separated list of valid class names):
另一种方法,以防你也想上这门课。如果类未定义,将返回 nil,因此您不必捕获异常。
Another approach, in case you want to get the class too. Will return nil if the class isn't defined, so you don't have to catch an exception.