如何检查 Ruby 中是否已经存在一个类?
我的代码是:
puts "enter the name of the Class to see if it exists"
nameofclass=gets.chomp
eval (" #{nameofclass}...... Not sure what to write here")
我在考虑使用:
eval "#{nameofclass}ancestors. ....."
您可以使用Module.const_get
方法获取字符串引用的常量。它将返回该常量(通常类别由常量引用)。然后,您可以检查该常量是否为类别。
我会按照以下方式进行操作:
def class_exists?(class_name)
klass = Module.const_get(class_name)
return klass.is_a?(Class)
rescue NameError
return false
end
另外,如果可能的话,我总是避免在接受用户输入时使用eval
;我怀疑这不会用于任何严肃的应用程序,但了解安全风险也是值得的。
if defined?(MyClassName) == 'constant' && MyClassName.class == Class
puts "its a class"
end
注意:需要进行类检查,例如:Hello = 1
puts defined?(Hello) == 'constant' # returns true
回答原问题:
puts "enter the name of the Class to see if it exists"
nameofclass=gets.chomp
eval("defined?(#{nameofclass}) == 'constant' and #{nameofclass}.class == Class")
defined?(MyClassName) == 'constant' && MyClassName.is_a?(Class)
看起来更直观。 - Jignesh Goheldefined? Object.const_get("array".capitalize)
返回 "method",而运行 defined? Array
返回 "constant"? - kamalirb(main):003:0> defined? TestingTesting::Testing
=> nil
irb(main):004:0> RUBY_VERSION
=> "2.6.1"
- Sam Saffron如果你想在特定作用域内查找常量,可以通过调用Module#const_defined?("SomeClass")
来避免从Module.const_get
中解救出NameError
异常。
一个常见的作用域是Object,例如:Object.const_defined?("User")
。
参见:" Module"。
>> Object.const_defined?("MyClass") # false
>> MyClass # MyClass
>> Object.const_defined?("MyClass") # true
这至少在Rails控制台中是这样的,可能因环境而异。 - carpeliam类名是常量。您可以使用defined?
方法来查看是否已定义常量。
defined?(String) # => "constant"
defined?(Undefined) # => nil
如果您感兴趣,您可以阅读更多关于defined?
的工作原理。
defined?(DatabaseCleaner) # => nil
require 'database_cleaner'
defined?(DatabaseCleaner) # => constant
Kernel.const_defined?("Fixnum") # => true
Loading test environment (Rails 4.2.5.1)
2.2.1 :001 > Kernel.const_defined?('ApiProvider')
=> false
2.2.1 :002 > ApiProvider
=> ApiProvider
2.2.1 :003 > Kernel.const_defined?('ApiProvider')
=> true
- Jignesh Gohel以下是我有时用来解决这个问题的方法。您可以像下面这样向String类添加以下方法:
class String
def to_class
my_const = Kernel.const_get(self)
my_const.is_a?(Class) ? my_const : nil
rescue NameError
nil
end
def is_a_defined_class?
true if self.to_class
rescue NameError
false
end
end
然后:
'String'.to_class
=> String
'unicorn'.to_class
=> nil
'puppy'.is_a_defined_class?
=> false
'Fixnum'.is_a_defined_class?
=> true
def class_exists?(class_name)
eval("defined?(#{class_name}) && #{class_name}.is_a?(Class)") == true
end
class_name = "Blorp"
class_exists?(class_name)
=> false
class_name = "String"
class_exists?(class_name)
=> true
用一句话概括,我会写:
!!Module.const_get(nameofclass) rescue false
nameofclass
属于已定义的类时,该函数将返回true
。Bla="some string" ; !!Module.const_get(:Bla) rescue false
返回true。 - nash
class Foo
end
那么我们可以使用 Object.const_defined?("Foo")
。如果您的类在任何模块中,例如。
module Bar
class Foo
end
end
那么我们可以使用Module.const_get("Bar::Foo")
。
请注意,如果Module.const_get('Bar::Foo')
找不到类,则会引发异常。而Object.const_defined?('Foo')
将返回true
或false
。
klass.is_a?(Class) || klass.is_a?(Module)
。带命名空间的名称可以在这个方法中工作。例如class_exists?('Delayed::Worker')
。非常不错。 - Douglas Lovell