Я читал эту книгу о Ruby, а затем еще один пример, который я не очень хорошо понял:
CONST = "outer"
module Mod
CONST = 1
def Mod.method1
# module method
CONST + 1
end
end
module Mod::Inner
def (Mod::Inner).method2
CONST + " scope"
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Mod::Inner::method2 # => "outer scope"
Не могли бы вы объяснить мне это (подробное объяснение), чтобы я мог полностью понять, как работает область видимости в Ruby. Спасибо.
2 ответа
Константы в Ruby (идентификаторы, начинающиеся с заглавной буквы) доступны на основе лексической области видимости, в которой они определены / доступны.
В method1
CONST
в области Mod
имеет приоритет над самым внешним CONST
. В method2
CONST
в области Mod
не виден лексически, поэтому осуществляется доступ к самому внешнему CONST
.
Что касается самих определений методов, когда имя уточняется с помощью предшествующей константы модуля (например, Mod
или Mod::Inner
), метод определяется как "метод модуля", а не как метод экземпляра self.class
(по умолчанию).
Имена в иерархии модуля / метода разделяются знаком ::
или, в качестве альтернативы, в случае разделителя между модулем и методом модуля, .
.
Обновление : обратите внимание, что причина, по которой константы Mod
не видны для method2
, заключается в том, что Mod
не был отдельно "открыт". Определение пропущено непосредственно к Mod::Inner
. Если код был изменен на:
module Mod
module Inner
def (Mod::Inner).method2
...
Тогда константы Mod
будут доступны для method2
и будут иметь приоритет над любыми во внешней области видимости.
Вы можете найти хорошее объяснение поиска в Ruby Constant здесь
Я бы поделился фрагментами кода с некоторыми пояснениями:
CONST = "outer"
module Mod
CONST = 1
def Mod.method1
# module method
Module.nesting # => [Mod]
CONST + 1
end
end
module Mod::Inner
def (Mod::Inner).method2
Module.nesting # => [Mod::Inner]
CONST + " scope"
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Mod::Inner::method2 # => "outer scope"
Взгляните на оценку Module.nesting
выше (Mod::Inner).method2
ищет в Mod::Inner
, как указано во вложении для CONST
, которое не находит до того, как вызовет основной объект для CONST
В приведенном ниже примере вы увидите, что Mod::Inner.method2
вызывает Mod :: Inner, а затем Mod для поиска найденного CONST
, поэтому нет необходимости вызывать CONST
в объекте
module Mod
CONST = 1
def Mod.method1
Module.nesting # => [Mod]
CONST + 1
end
module Inner
def (Mod::Inner).method2
Module.nesting # => [Mod::Inner, Mod]
CONST.to_s + " scope"
end
end
end
Mod::CONST # => 1
Mod.method1 # => 2
Object::CONST # => "outer"
Mod::Inner::method2 # => "1 scope"
В случае сомнений используйте определение вложенного класса / константы вместо лексического, он всегда будет делать правильные вещи, как ожидалось.
Похожие вопросы
Новые вопросы
ruby
Ruby - это многоплатформенный динамический объектно-ориентированный интерпретируемый язык с открытым исходным кодом. Тег [ruby] предназначен для вопросов, связанных с языком Ruby, включая его синтаксис и его библиотеки. Вопросы Ruby on Rails должны быть помечены [ruby-on-rails].