Подтвердить что ты не робот

Методы экземпляров в модулях

Рассмотрим следующий код:

module ModName
  def aux
    puts 'aux'
  end
end

Если заменить module на class, мы можем сделать следующее:

ModName.new.aux

Модули не могут быть установлены. Есть ли способ вызвать метод aux в модуле?

4b9b3361

Ответ 1

Подумайте, что такое aux. Какой объект ответит на aux? Это метод экземпляра, который означает, что экземпляры классов, которые включают ModName, будут отвечать на него. Сам модуль ModName не является экземпляром такого класса. Это также не сработает, если вы определили ModName как класс - вы не можете вызвать метод экземпляра без экземпляра.

Модули очень похожи на классы, которые могут быть смешаны с другими классами для добавления поведения. Когда класс смешивается в модуле, все экземпляры экземпляра модуля становятся экземплярами метода класса. Это способ реализации множественного наследования.

Они также служат заменой пространств имен, поскольку каждый модуль определяет пространство имен. Но это несколько не связано. (Кстати, классы также имеют собственные пространства имен, но создание класса означает, что вы создадите его экземпляры, поэтому они концептуально ошибочны для этой цели.)

Ответ 2

Вы можете сделать это следующим образом:

module ModName
  def aux
    puts 'aux'
  end
  module_function :aux
end

а затем просто назовите его:

ModName.aux

Ответ 3

Вы также можете сказать

module ModName
  extend self

  def aux
    puts 'aux'
  end
end

Затем вы можете включить модуль нормально, но также вызвать методы через ModName.

Ответ 4

определение модуля оценивается как "это...", почему?

В Ruby все выражается, нет заявлений или деклараций. Это означает, что каждый элемент оценивает значение. (Тем не менее, это не обязательно означает, что он оценивает полезное значение. Например, метод puts всегда оценивается как nil, как и выражение определения метода def (за исключением Rubinius, где def выражение оценивает объект CompiledMethod для определяемого метода).)

Итак, если все оценивает значение, что должно оценивать выражение определения модуля? Ну, есть несколько кандидатов: он может оценивать до nil, как и выражение определения метода. Или он мог бы оценить сам объект модуля, ведь это то, что мы определяем, не так ли? Но на самом деле, Matz выбрал третий вариант: выражения определения (и класса) фактически оценивают то, что оценивает последнее выражение внутри тела определения модуля. (Это позволяет легко имитировать две другие возможности, просто поместив nil или self в качестве последнего выражения внутри тела определения модуля.)

В вашем случае последнее выражение внутри тела определения модуля - это назначение. Но, задание? Что, черт возьми, это возвращается? Разве это не утверждение? Нет, не в Руби. Все это выражение, а присваивания не являются исключением: выражения присваивания оцениваются независимо от того, что оценивает правая сторона. Здесь правая часть выражения присваивания представляет собой строковый литерал, который оценивает строковый объект.

Итак, выражение определения всего модуля оценивается как строка 'this is a const in module'.

Ответ 5

И еще немного...

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"

Ответ 6

class Foo
  include ModName
end
Foo.new.aux
# output: aux