Путание поведения const_get в Ruby?

Согласно документации 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 ?

Спасибо

20
задан horseyguy 2 July 2010 в 12:19
поделиться

1 ответ

Вы правильно запутались ... В документе не говорится, что 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 , как в последней части моего примера.

Надеюсь, я правильно понял, потому что меня все еще сбивают с толку постоянные поиски: -)

11
ответ дан 30 November 2019 в 01:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: