Другой случай возможного применения является декоратором, который делегирует все вызовы к обернутому экземпляру. Конкретная реализация декоратора может переопределить только те методы, где функциональность добавляется:
public interface Foo {
public void bar();
}
public abstract class FooDecorator implements Foo {
private final Foo wrapped;
public FooDecorator(Foo wrapped) { this.wrapped = wrapped; }
public void bar() { wrapped.bar(); }
}
public class TracingFoo extends FooDecorator {
//Omitting constructor code...
public void bar() {
log("Entering bar()");
super.bar();
log("Exiting bar()");
}
}
, Хотя я действительно не вижу necessarity для объявления FooDecorator как краткого обзора (неабстрактный пример: HttpServletRequestWrapper).
Вы можете использовать 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
при принятии пользовательского ввода; Я сомневаюсь, что это будет использоваться для каких-либо серьезных приложений, но стоит знать о рисках безопасности.
Имена классов являются константами. Вы можете использовать метод defined?
, чтобы узнать, была ли определена константа.
defined?(String) # => "constant"
defined?(Undefined) # => nil
Вы можете узнать больше о том, как defined?
работает, если вам интересно.
возможно вы сможете это сделать с определенным?
например:
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?(DatabaseCleaner) # => nil
require 'database_cleaner'
defined?(DatabaseCleaner) # => constant
Вы можете избежать необходимости спасать NameError из Module.const_get
, если вы ищете константу в определенной области видимости, вызвав Module#const_defined?("SomeClass")
.
Обычной областью видимости для этого является Object, например: Object.const_defined?("User")
.
См: "Module".
Я использовал это, чтобы увидеть, был ли класс загружен во время выполнения:
def class_exists?(class_name)
ObjectSpace.each_object(Class) {|c| return true if c.to_s == class_name }
false
end