Ruby Language
интроспекция
Поиск…
Просмотр методов объекта
Проверка объекта
Вы можете найти общедоступные методы, на которые объект может ответить, используя methods
или методы public_methods
, которые возвращают массив символов:
class Foo
def bar; 42; end
end
f = Foo.new
def f.yay; 17; end
p f.methods.sort
#=> [:!, :!=, :!~, :<=>, :==, :===, :=~, :__id__, :__send__, :bar, :class, :clone,
#=> :define_singleton_method, :display, :dup, :enum_for, :eql?, :equal?, :extend,
#=> :freeze, :frozen?, :hash, :inspect, :instance_eval, :instance_exec,
#=> :instance_of?, :instance_variable_defined?, :instance_variable_get,
#=> :instance_variable_set, :instance_variables, :is_a?, :itself, :kind_of?,
#=> :method, :methods, :nil?, :object_id, :private_methods, :protected_methods,
#=> :public_method, :public_methods, :public_send, :remove_instance_variable,
#=> :respond_to?, :send, :singleton_class, :singleton_method, :singleton_methods,
#=> :taint, :tainted?, :tap, :to_enum, :to_s, :trust, :untaint, :untrust,
#=> :untrusted?, :yay]
Для более целевого списка вы можете удалить методы, общие для всех объектов, например
p (f.methods - Object.methods).sort
#=> [:bar,:yay]
Кроме того, вы можете передать false
methods
или public_methods
:
p f.methods(false) # public and protected singleton methods of `f`
#=> [:yay]
p f.public_methods(false)
#=> [:yay, :bar]
Вы можете найти частные и защищенные методы объекта с использованием private_methods
и protected_methods
:
p f.private_methods.sort
#=> [:Array, :Complex, :DelegateClass, :Float, :Hash, :Integer, :Rational, :String,
#=> :__callee__, :__dir__, :__method__, :`, :abort, :at_exit, :autoload, :autoload?,
#=> :binding, :block_given?, :caller, :caller_locations, :catch,
#=> :default_src_encoding, :eval, :exec, :exit, :exit!, :fail, :fork, :format, :gem,
#=> :gem_original_require, :gets, :global_variables, :initialize, :initialize_clone,
#=> :initialize_copy, :initialize_dup, :irb_binding, :iterator?, :lambda, :load,
#=> :local_variables, :loop, :method_missing, :open, :p, :print, :printf, :proc,
#=> :putc, :puts, :raise, :rand, :readline, :readlines, :require, :require_relative,
#=> :respond_to_missing?, :select, :set_trace_func, :singleton_method_added,
#=> :singleton_method_removed, :singleton_method_undefined, :sleep, :spawn,
#=> :sprintf, :srand, :syscall, :system, :test, :throw, :trace_var, :trap,
#=> :untrace_var, :warn]
p f.protected_methods
#=> []
Как и methods
и public_methods
, вы можете передать false
в private_methods
и protected_methods
чтобы обрезать унаследованные методы.
Проверка класса или модуля
В дополнение к methods
public_methods
, protected_methods
и private_methods
, классы и модули выставляют instance_methods
, public_instance_methods
, protected_instance_methods
и private_instance_methods
для определения методов, открытых для объектов, которые наследуются от класса или модуля. Как и выше, вы можете передать false
этим методам, чтобы исключить унаследованные методы:
p Foo.instance_methods.sort
#=> [:!, :!=, :!~, :<=>, :==, :===, :=~, :__id__, :__send__, :bar, :class,
#=> :clone, :define_singleton_method, :display, :dup, :enum_for, :eql?,
#=> :equal?, :extend, :freeze, :frozen?, :hash, :inspect, :instance_eval,
#=> :instance_exec, :instance_of?, :instance_variable_defined?,
#=> :instance_variable_get, :instance_variable_set, :instance_variables,
#=> :is_a?, :itself, :kind_of?, :method, :methods, :nil?, :object_id,
#=> :private_methods, :protected_methods, :public_method, :public_methods,
#=> :public_send, :remove_instance_variable, :respond_to?, :send,
#=> :singleton_class, :singleton_method, :singleton_methods, :taint,
#=> :tainted?, :tap, :to_enum, :to_s, :trust, :untaint, :untrust, :untrusted?]
p Foo.instance_methods(false)
#=> [:bar]
Наконец, если вы забудете имена большинства из них в будущем, вы можете найти все эти методы, используя methods
:
p f.methods.grep(/methods/)
#=> [:private_methods, :methods, :protected_methods, :public_methods,
#=> :singleton_methods]
p Foo.methods.grep(/methods/)
#=> [:public_instance_methods, :instance_methods, :private_instance_methods,
#=> :protected_instance_methods, :private_methods, :methods,
#=> :protected_methods, :public_methods, :singleton_methods]
Просмотр переменных экземпляра объекта
Можно запросить объект о его переменных instance_variables
, используя instance_variables
, instance_variable_defined?
, и instance_variable_get
, и измените их, используя instance_variable_set
и remove_instance_variable
:
class Foo
attr_reader :bar
def initialize
@bar = 42
end
end
f = Foo.new
f.instance_variables #=> [:@bar]
f.instance_variable_defined?(:@baz) #=> false
f.instance_variable_defined?(:@bar) #=> true
f.instance_variable_get(:@bar) #=> 42
f.instance_variable_set(:@bar, 17) #=> 17
f.bar #=> 17
f.remove_instance_variable(:@bar) #=> 17
f.bar #=> nil
f.instance_variables #=> []
Имена переменных экземпляра включают символ @
. Вы получите сообщение об ошибке:
f.instance_variable_defined?(:jim)
#=> NameError: `jim' is not allowed as an instance variable name
Просмотр глобальных и локальных переменных
Kernel
предоставляет методы для получения списка global_variables
и local_variables
:
cats = 42
$demo = "in progress"
p global_variables.sort
#=> [:$!, :$", :$$, :$&, :$', :$*, :$+, :$,, :$-0, :$-F, :$-I, :$-K, :$-W, :$-a,
#=> :$-d, :$-i, :$-l, :$-p, :$-v, :$-w, :$., :$/, :$0, :$1, :$2, :$3, :$4, :$5,
#=> :$6, :$7, :$8, :$9, :$:, :$;, :$<, :$=, :$>, :$?, :$@, :$DEBUG, :$FILENAME,
#=> :$KCODE, :$LOADED_FEATURES, :$LOAD_PATH, :$PROGRAM_NAME, :$SAFE, :$VERBOSE,
#=> :$\, :$_, :$`, :$binding, :$demo, :$stderr, :$stdin, :$stdout, :$~]
p local_variables
#=> [:cats]
В отличие от переменных экземпляра нет методов специально для получения, настройки или удаления глобальных или локальных переменных. Поиск такой функциональности обычно является признаком того, что ваш код должен быть переписан, чтобы использовать хэш для хранения значений. Однако, если вы должны изменить глобальные или локальные переменные по имени, вы можете использовать eval
со строкой:
var = "$demo"
eval(var) #=> "in progress"
eval("#{var} = 17")
p $demo #=> 17
По умолчанию eval
будет оценивать ваши переменные в текущей области. Чтобы оценить локальные переменные в другой области, вы должны зафиксировать привязку, где существуют локальные переменные.
def local_variable_get(name, bound=nil)
foo = :inside
eval(name,bound)
end
def test_1
foo = :outside
p local_variable_get("foo")
end
def test_2
foo = :outside
p local_variable_get("foo",binding)
end
test_1 #=> :inside
test_2 #=> :outside
В приведенном выше test_1
не передал привязку к local_variable_get
, и поэтому eval
был выполнен в контексте этого метода, где локальная переменная с именем foo
была установлена :inside
.
Просмотр переменных класса
Классы и модули имеют одинаковые методы для интроспекции переменных экземпляра как любого другого объекта. Класс и модули также имеют похожие методы для запроса переменных класса ( @@these_things
):
p Module.methods.grep(/class_variable/)
#=> [:class_variables, :class_variable_get, :remove_class_variable,
#=> :class_variable_defined?, :class_variable_set]
class Foo
@@instances = 0
def initialize
@@instances += 1
end
end
class Bar < Foo; end
5.times{ Foo.new }
3.times{ Bar.new }
p Foo.class_variables #=> [:@@instances]
p Bar.class_variables #=> [:@@instances]
p Foo.class_variable_get(:@@instances) #=> 8
p Bar.class_variable_get(:@@instances) #=> 8
Подобно переменным экземпляра, имя переменных класса должно начинаться с @@
, или вы получите сообщение об ошибке:
p Bar.class_variable_defined?( :instances )
#=> NameError: `instances' is not allowed as a class variable name