#ruby
#ruby #ruby-2.2
Вопрос:
Я просто застрял на этом на некоторое время. Возьмите эту базу:
module Top
class Test
end
module Foo
end
end
Позже я могу определить классы внутри Foo
, которые расширяются Test
, выполнив это:
module Top
module Foo
class SomeTest < Test
end
end
end
Однако, если я попытаюсь минимизировать отступ, используя ::
для указания модуля:
module Top::Foo
class Failure < Test
end
end
Это не удается с:
Ошибка имени: неинициализированная константа Top::Foo::Test
Это ошибка или просто логическое следствие того, как Ruby разрешает имена переменных?
Ответ №1:
Это ошибка или это просто логическое следствие
Это «причуда». Некоторые считают это ошибкой.
Родительские области, используемые для поиска неразрешенных констант, определяются вложенностью модуля. Так уж получилось, что при использовании module Top::Foo
он создает только один уровень вложенности вместо двух. Обратите внимание:
module Top
module Foo
class SomeTest
Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top]
end
end
end
module Top::Foo
class SomeTest
Module.nesting # => [Top::Foo::SomeTest, Top::Foo]
end
end
Комментарии:
1. Для меня это звучит как ошибка: P, но очень информативный ответ, спасибо
2. Я бы сказал, что считаю это ошибкой, кто-нибудь нашел сообщение об ошибке в ruby об этом? Я хотел бы внести свой вклад в обсуждение и посмотреть, что будет связано с исправлением этого.
3. Примечание: найдена ссылка, указывающая, что это намеренно здесь
4. Похоже, это сообщение об ошибке для такого поведения. Будем надеяться, что Matz решит забрать его. 🙂
Ответ №2:
Это ожидаемо. Использование ::
изменяет область постоянного поиска и ожидает Test
, что она будет определена в Top::Foo
.
Чтобы получить ожидаемый результат, вы могли бы написать:
module Top::Foo
class SomeTest < Top::Test
end
end
или:
module Top
class Foo::SomeTest < Test
end
end
или даже:
class Top::Foo::SomeTest < Top::Test
end