Рассмотрим следующий код:
module ModName
def aux
puts 'aux'
end
end
Если заменить module
на class
, мы можем сделать следующее:
ModName.new.aux
Модули не могут быть установлены. Есть ли способ вызвать метод aux
в модуле?
Рассмотрим следующий код:
module ModName
def aux
puts 'aux'
end
end
Если заменить module
на class
, мы можем сделать следующее:
ModName.new.aux
Модули не могут быть установлены. Есть ли способ вызвать метод aux
в модуле?
Подумайте, что такое aux
. Какой объект ответит на aux
? Это метод экземпляра, который означает, что экземпляры классов, которые включают ModName, будут отвечать на него. Сам модуль ModName не является экземпляром такого класса. Это также не сработает, если вы определили ModName как класс - вы не можете вызвать метод экземпляра без экземпляра.
Модули очень похожи на классы, которые могут быть смешаны с другими классами для добавления поведения. Когда класс смешивается в модуле, все экземпляры экземпляра модуля становятся экземплярами метода класса. Это способ реализации множественного наследования.
Они также служат заменой пространств имен, поскольку каждый модуль определяет пространство имен. Но это несколько не связано. (Кстати, классы также имеют собственные пространства имен, но создание класса означает, что вы создадите его экземпляры, поэтому они концептуально ошибочны для этой цели.)
Вы можете сделать это следующим образом:
module ModName
def aux
puts 'aux'
end
module_function :aux
end
а затем просто назовите его:
ModName.aux
Вы также можете сказать
module ModName
extend self
def aux
puts 'aux'
end
end
Затем вы можете включить модуль нормально, но также вызвать методы через ModName.
определение модуля оценивается как "это...", почему?
В Ruby все выражается, нет заявлений или деклараций. Это означает, что каждый элемент оценивает значение. (Тем не менее, это не обязательно означает, что он оценивает полезное значение. Например, метод puts
всегда оценивается как nil
, как и выражение определения метода def
(за исключением Rubinius, где def
выражение оценивает объект CompiledMethod
для определяемого метода).)
Итак, если все оценивает значение, что должно оценивать выражение определения модуля? Ну, есть несколько кандидатов: он может оценивать до nil
, как и выражение определения метода. Или он мог бы оценить сам объект модуля, ведь это то, что мы определяем, не так ли? Но на самом деле, Matz выбрал третий вариант: выражения определения (и класса) фактически оценивают то, что оценивает последнее выражение внутри тела определения модуля. (Это позволяет легко имитировать две другие возможности, просто поместив nil
или self
в качестве последнего выражения внутри тела определения модуля.)
В вашем случае последнее выражение внутри тела определения модуля - это назначение. Но, задание? Что, черт возьми, это возвращается? Разве это не утверждение? Нет, не в Руби. Все это выражение, а присваивания не являются исключением: выражения присваивания оцениваются независимо от того, что оценивает правая сторона. Здесь правая часть выражения присваивания представляет собой строковый литерал, который оценивает строковый объект.
Итак, выражение определения всего модуля оценивается как строка 'this is a const in module'
.
И еще немного...
module Y
def Y.a
puts "a"
end
def Y.b
c
end
def self.c
puts "b -- c"
end
end
вызов (без ".new" ):
Y.a #=> "a"
Y.b #=> "b -- c"
Y.c #=> "b -- c"
class Foo
include ModName
end
Foo.new.aux
# output: aux