Модули Ruby и расширения

В какой ситуации находится код:

module M
   extend self
   def greet
    puts "hello"
   end

end

более полезно использовать над чем-то вроде:

module M
   def self.greet
    puts "hello"
   end
end

В верхней части, один - это метод экземпляра, который расширяется, а последний - только метод класса, но при вызове любого из методов вам нужно будет M.greet, правильно? Мне было просто любопытно, может ли кто-нибудь пролить свет на то, когда использовать один код над другим. Спасибо!

Ответы

Ответ 1

Первый пример обычно - это способ, которым люди достигают функциональности module_function (когда они не знают о существовании этого метода).

A module_function - это метод экземпляра и метод класса. В вашем втором примере кода метод - это просто метод класса.

Ответ 2

Это можно сделать с помощью первого примера, но не второго:

include M
greet

Ответ 3

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

Концепция саморасширяющегося модуля позволяет использовать модуль в обоих направлениях; либо как автономное пространство имен, либо как mixin. Рассмотрим этот модуль:

module M
  def bar
    puts "bar"
  end
end
class C
  include M
end

Он имеет метод экземпляра и может быть смешан с другим объектом. Он не имеет метода модуля и не может поэтому использоваться как пространство имен:

puts M::bar # => undefined method `bar' for M:Module
puts C.bar  # => this is bar

Но модуль является просто объектом класса Module, поскольку мы можем продемонстрировать

puts M.class   # => Module

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

module M
  extend self
  def bar
    puts "bar"
  end
end
puts M::bar # => this is bar
puts C.bar  # => this is bar