Согласно документации mod.const_get(sym)
"Возвращает значение именованной константы в модификации".
Я также знаю это const_get
по умолчанию может искать цепочку наследования получателя. Так следующие работы:
class A; HELLO = :hello; end
class B < A; end
B.const_get(:HELLO) #=> :hello
Я также знаю, что классы в Ruby разделяют на подклассы Object
, так, чтобы можно было использовать const_get
для поиска 'глобальных' констант даже при том, что получатель является нормальным классом:
class C; end
C.const_get(:Array) #=> Array
Однако и это - то, где я смущен - модули не разделяют на подклассы Object
. Итак, почему я могу все еще искать 'глобальные' константы от использования модуля const_get
? Почему следующее работает?
module M; end
M.const_get(:Array) #=> Array
Если документация корректна - const_get
просто ищет константу, определенную под получателем или его суперклассами. Но в коде сразу выше, Object
не суперкласс M
, итак, почему возможно искать Array
?
Спасибо
Вы правильно запутались ... В документе не говорится, что Ruby делает особый случай для поиска констант в Modules
и был изменен , чтобы указать это явно . Если константа не была найдена в нормальной иерархии, Ruby перезапускает поиск из Object
, как и , найденный в источнике .
Постоянный поиск сам по себе может немного запутать. Возьмем следующий пример:
module M
Foo = :bar
module N
# Accessing Foo here is fine:
p Foo # => bar
end
end
module M::N
# Accessing Foo here isn't
p Foo # => uninitialized constant M::N::Foo
end
p M::N.const_get :Foo # => uninitialized constant M::N::Foo
Однако в обоих местах доступ к константам уровня Object
, например Array
, не вызывает проблем (слава богу!). Что происходит, так это то, что Ruby поддерживает список «открытых определений модулей». Если у константы есть явная область видимости, скажем LookHereOnly :: Foo
, то будет выполняться поиск только LookHereOnly
и включенных в нее модулей. Если область видимости не указана (например, Foo
в приведенном выше примере), Ruby просматривает определения открытых модулей, чтобы найти константу Foo
: M :: N
, затем M
и, наконец, Object
. Самым верхним открытым определением модуля всегда является Объект
.
Итак, M :: N.const_get: Foo
эквивалентно доступу к Foo
, когда открытыми классами являются только M :: N
и Object
, как в последней части моего примера.
Надеюсь, я правильно понял, потому что меня все еще сбивают с толку постоянные поиски: -)