Я не уверен, в чем проблема.Я понимаю, что там написано неинициализировано , но я не уверен почему.Кажется, он ищет константу вместо чтения класса?
Мне не понятно, что вы имеете в виду под "чтением класса".Да, Руби ищет постоянную.Имена переменных, начинающиеся с заглавной буквы, являются константами, поэтому HtmlBody
- это константа, HeadingTags
- это константа, а HtmlBody::HeadingTags
- это константа HeadingTags
, расположенная в классе или модуле, на который ссылается константа HtmlBody
.
Как вы должны включать классы, расположенные в отдельных файлах внутри модуля?
Пространство имен внутри модуля определяется путем определения класса внутри модуля,Если вы уверены , что модуль уже существует, вы можете определить класс следующим образом:
class HtmlBody::HeadingTags
# …
end
Однако, если HtmlBody
не определено (или не является классом или модулем), это не удастся.
module HtmlBody
class HeadingTags
# …
end
end
Это будет гарантировать, что модуль HtmlBody
будет создан, если он не существует (и просто повторно открыт, если он уже существует).
Существует также небольшое различие в правилах постоянного поиска между ними, что, однако, не относится к вашему вопросу (но имейте это в виду).
Это то, чего мне не хватает в Ruby и require / require_relative вероятно.
Действительно, ваш вопрос проистекает из фундаментального недопонимания того, что Kerne#load
/ Kernel#require
/Kernel#require_relative
делает.
Вот очень сложное, подробное, подробное объяснение всех невероятно запутанных вещей, которые делают эти три метода.Готовься!Вы готовы?Здесь мы идем:
Они запускают файл.
Подождите ... это все?Да это оно!Это все, что нужно сделать.Они запускают файл.
Итак, что происходит, когда вы запускаете файл, который выглядит следующим образом:
class HeadingTags
# …
end
Он определяет класс с именем HeadingTags
впространство имен верхнего уровня, верно?
Хорошо, так что же произойдет, когда мы сейчас сделаем это:
require_relative './html_body/HeadingTags'
Ну, мы сказали, что require_relative
просто запускаетфайл.И мы сказали, что запуск этого файла определяет класс с именем HeadingTags
в пространстве имен верхнего уровня.Следовательно, это, очевидно, определит класс с именем HeadingTags
в пространстве имен верхнего уровня.
Теперь посмотрим на ваш код: что происходит, когда мы делаем это:
module HtmlBody
require_relative './html_body/HeadingTags'
end
Опять же, мы сказали, что require_relative
просто запускает файл.Ничего больше.Не меньше.Просто запустите файл.И что мы сказали, что работает этот файл?Он определяет класс с именем HeadingTags
в пространстве имен верхнего уровня.
Итак, что будет делать вызов require_relative
из определения модуля HtmlBody
?Он определит класс с именем HeadingTags
в пространстве имен верхнего уровня .Поскольку require_relative
просто запускает файл, и, следовательно, результат будет точно таким же, как и запуск файла, и результат запуска файла заключается в том, что он определяет класс в пространстве имен верхнего уровня.
Итак,как вы на самом деле достигаете того, что вы пытаетесь сделать?Что ж, если вы хотите определить класс внутри модуля, вы должны ... определить класс внутри модуля!
lib / html_body.rb
require_relative 'html_body/heading_tags'
require_relative 'html_body/anchor_tags'
require_relative 'html_body/img_tags'
module HtmlBody; end
lib / html_body / heading_tags.rb
module HtmlBody
class HeadingTags
# …
end
end
lib / html_body / anchor_tags.rb
module HtmlBody
class AnchorTags
# …
end
end
lib / html_body/img_tags.rb
module HtmlBody
class ImgTags
# …
end
end
main.rb
require_relative 'lib/html_body'
HtmlBody::HeadingTags.new