Почему выражение `Object.singleton_class.instance_method (: уточнение)` вызывает `NameError`? - PullRequest
0 голосов
/ 28 апреля 2018

Как мы знаем, метод Module#refine является методом частного экземпляра в классе Module:

% Module.private_instance_methods(false)
[:remove_const, :method_added, :append_features, :method_removed, 
:method_undefined, :extend_object, :prepend_features, :using, :refine, 
:initialize, :initialize_copy, :initialize_clone, :public, :protected, 
:module_function, :private, :included, :extended, :prepended]

Это означает, что сам класс Object может вызывать метод refine с использованием Object#send или BasicObject#__send__, поскольку Object.singleton_class.ancestors.include?(Module) имеет значение true.

Но фактическая ошибка undefined method возникает при выполнении Object.refine:

# ./tmp/mytest.rb
Module.private_instance_methods(false).map do |m|
  begin
    p [m, Object.singleton_class.instance_method(m)]
  rescue StandardError => e
    p [m, e.exception]
  end
end

Вывод такой. Метод refine находится посередине.

% ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]
% ruby ./tmp/mytest.rb
[:remove_const, #<UnboundMethod: #<Class:Object>#remove_const>]
[:method_added, #<UnboundMethod: #<Class:Object>#method_added>]
[:append_features, #<NameError: undefined method `append_features' for class `#<Class:Object>'>]
[:method_removed, #<UnboundMethod: #<Class:Object>#method_removed>]
[:method_undefined, #<UnboundMethod: #<Class:Object>#method_undefined>]
[:extend_object, #<NameError: undefined method `extend_object' for class `#<Class:Object>'>]
[:prepend_features, #<NameError: undefined method `prepend_features' for class `#<Class:Object>'>]
[:using, #<UnboundMethod: #<Class:Object>#using>]
[:refine, #<NameError: undefined method `refine' for class `#<Class:Object>'>]
[:initialize, #<UnboundMethod: #<Class:Object>#initialize>]
[:initialize_copy, #<UnboundMethod: #<Class:Object>#initialize_copy>]
[:initialize_clone, #<UnboundMethod: #<Class:Object>#initialize_clone>]
[:public, #<UnboundMethod: #<Class:Object>#public>]
[:protected, #<UnboundMethod: #<Class:Object>#protected>]
[:module_function, #<NameError: undefined method `module_function' for class `#<Class:Object>'>]
[:private, #<UnboundMethod: #<Class:Object>#private>]
[:included, #<UnboundMethod: #<Class:Object>#included>]
[:extended, #<UnboundMethod: #<Class:Object>#extended>]
[:prepended, #<UnboundMethod: #<Class:Object>#prepended>]

В приведенном выше результате, кроме метода refine, append_features, prepend_features, extend_object и module_function метод повышают NameError, тогда как другие методы преуспевают при поиске метода.

Это выглядит так любопытно, что я хочу знать, что происходит.

1 Ответ

0 голосов
/ 28 апреля 2018

При осмотре похоже, что :refine - это UnboundMethod, но я нашел это pry вокруг. Из консоли:

Module.private_instance_methods(:false)

Вы заметите:

 [ 76]                     refine(arg1)                    Module (unbound)

Эта документация должна объяснить то, как NameError поднимается в вашем примере кода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...