расширение self в модуле

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

Кажется, что эти две части кодов выполняют одну и ту же работу, но я хотел бы понять, почему я предпочел бы использовать тот или иной

Первый пример:

 module MyModule 
  extend self

  def first_method
  end

  def second_method
  end

end
  

Второй пример:

 module MyModule 

  def self.first_method
  end

  def self.second_method
  end

end
  

Комментарии:

1. Это чисто Ruby вопрос, поэтому у него не должно быть тега Rails. Одним из следствий является то, что читатели, которые отфильтровали вопросы Rails (но не вопросы Ruby), не увидят ваш вопрос.

Ответ №1:

Ваш первый пример определяет два метода экземпляра и делает их также доступными как методы класса (или модуля) через extend :

 module MyModule 
  def first_method; end
  def second_method; end
end

MyModule.instance_methods         #=> [:second_method, :first_method]
MyModule.methods - Module.methods #=> []

MyModule.extend MyModule

MyModule.instance_methods         #=> [:second_method, :first_method]
MyModule.methods - Module.methods #=> [:second_method, :first_method]
  

В то время как ваш второй пример просто определяет два метода класса (или модуля) и не содержит методов экземпляра:

 module MyModule 
  def self.first_method; end
  def self.second_method; end
end

MyModule.instance_methods         #=> []
MyModule.methods - Module.methods #=> [:second_method, :first_method]
  

Первый вариант может быть полезен, когда вы хотите предоставить некоторые служебные функции, которые можно вызывать как:

 MyModule.first_method
  

или быть включенным в другие модули / классы:

 class Foo
  include MyModule

  def another_method
    first_method     # <- no explicit receiver needed
  end
end
  

Ruby также предоставляет вспомогательный метод module_function для определения методов таким образом:

 module MyModule
  def first_method
  end
  module_function :first_method
end
  

Он добавляет метод в качестве методов класса и делает метод экземпляра частным. Вот как работают методы в Kernel .

Комментарии:

1. спасибо, что нашли время и за ваш наглядный пример 🙂

2. Поскольку вы зашли так далеко, подумайте также о том, чтобы упомянуть self.included(klass) идиому для включения одних методов и расширения других.