Как инициализировать переменные экземпляра модуля в Ruby?

У меня есть некоторые модули, в которых я бы хотел использовать переменные экземпляра. В настоящее время я инициализирую их следующим образом:

module MyModule
  def self.method_a(param)
    @var ||= 0
    # other logic goes here
  end
end

Я также мог бы вызвать метод init для их инициализации:

def init
  @var = 0
end

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

Есть ли лучший способ сделать это?

Ответ 1

Инициализировать их в определении модуля.

module MyModule
  # self here is MyModule
  @species = "frog"
  @color = "red polka-dotted"
  @log = []

  def self.log(msg)
    # self here is still MyModule, so the instance variables are still available
    @log << msg
  end
  def self.show_log
    puts @log.map { |m| "A #@color #@species says #{m.inspect}" }
  end
end

MyModule.log "I like cheese."
MyModule.log "There no mop!"
MyModule.show_log #=> A red polka-dotted frog says "I like cheese."
                  #   A red polka-dotted frog says "There no mop!"

Это задает переменные экземпляра, когда модуль определен. Помните, что вы можете повторно открыть модуль позже, чтобы добавить дополнительные переменные экземпляра и определения методов, или для переопределения существующих:

# continued from above...
module MyModule
  @verb = "shouts"
  def self.show_log
    puts @log.map { |m| "A #@color #@species #@verb #{m.inspect}" }
  end
end
MyModule.log "What going on?"
MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese."
                  #   A red polka-dotted frog shouts "There no mop!"
                  #   A red polka-dotted frog shouts "What going on?"

Ответ 2

Вы можете использовать:

def init(var=0)
 @var = var
end

И по умолчанию будет 0, если вы ничего не передадите.

Если вы не хотите называть его каждый раз, вы можете использовать что-то вроде этого:

module AppConfiguration
   mattr_accessor :google_api_key
   self.google_api_key = "123456789"
...

end

Ответ 3

для класса, я бы сказал следующее, поскольку инициализация вызывается всякий раз, когда вы .new новый экземпляр класса.

def initialize
   @var = 0
end

from Практический рубин:

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

Ответ 4

По-видимому, это плохая форма для инициализации переменных экземпляра в модуле в Ruby. (По причинам, которые я не совсем понимаю, но относится к порядку, в котором создаются вещи.)

Кажется, что наилучшей практикой является использование аксессуаров с ленивой инициализацией, например:

module MyModule
  def var
    @var ||= 0 
  end
end

Затем используйте var в качестве получателя для @var.

Ответ 5

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

module MyModule
  class << self; attr_accessor :var; end
end

MyModule.var
=> nil

MyModule.var = 'this is saved at @var'
=> "this is saved at @var"

MyModule.var    
=> "this is saved at @var"