Как я могу инициализировать переменные экземпляра модуля в Ruby? - PullRequest
76 голосов
/ 30 марта 2009

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

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

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

def init
  @var = 0
end

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

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

Ответы [ 5 ]

104 голосов
/ 30 марта 2009

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

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!"

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

# 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?"
5 голосов
/ 30 марта 2009

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

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

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

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

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

end
2 голосов
/ 15 апреля 2014

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

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

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

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

2 голосов
/ 09 января 2012

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

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"
2 голосов
/ 30 марта 2009

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

def initialize
   @var = 0
end

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

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

...