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

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

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

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

def init
  @var = 0
end

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

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

5 ответов


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

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's no mop!"
MyModule.show_log #=> A red polka-dotted frog says "I like cheese."
                  #   A red polka-dotted frog says "There's no mop!"

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

# 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's going on?"
MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese."
                  #   A red polka-dotted frog shouts "There's no mop!"
                  #   A red polka-dotted frog shouts "What's going on?"

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

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

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

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

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

end

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

def initialize
   @var = 0
end

С Практические Рубин:

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


Я ответил похожим вопрос, вы можете установить переменные экземпляра класса этим

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"

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

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

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

затем использовать var как геттер для @var.