Создание переменных модуля в Ruby

Есть ли способ создать переменную в модуле в Ruby, которая будет вести себя аналогично переменной класса? Я имею в виду, что к нему можно будет получить доступ без инициализации экземпляра модуля, но его можно изменить (в отличие от констант в модулях).


person Mark Szymanski    schedule 16.04.2011    source источник


Ответы (4)


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

module Site
  @@name = "StackOverflow"

  def self.setName(value)
    @@name = value
  end

  def self.name
    @@name
  end
end

Site.name            # => "StackOverflow"
Site.setName("Test")
Site.name            # => "Test"
person coreyward    schedule 16.04.2011
comment
+1 На самом деле, я думал, что термин «переменная класса» вводит в заблуждение. Классы - это частные случаи модулей, а переменные классов могут быть определены в модулях. Их следует называть модульными переменными. - person sawa; 17.04.2011
comment
@sawa: Это несколько вводит в заблуждение, но это то, что использует сама Ruby: defined?(@@foo) => "class variable". - person Andrew Grimm; 09.01.2012
comment
Или их можно было бы назвать статическими полями. Похоже, что они такие. - person Peter Ajtai; 11.05.2012
comment
@coreyward Привет, моя ошибка. Зачем нужны две переменные класса @@? Разве это не считается запахом кода, особенно если класс расширен для использования переменных класса? Я тестировал это и понял, что могу получить тот же результат от одной переменной экземпляра @. Есть ли конкретная причина для использования переменных класса? Спасибо за ответ. - person Cache; 25.01.2014
comment
@feed_me_code Это просто часть языка. Переменная класса находится в фактическом классе, а не в экземпляре класса. В большинстве случаев они будут вести себя одинаково, но не всегда. См. stackoverflow.com/questions/5890118/ для более подробного объяснения. - person coreyward; 26.01.2014
comment
почему разные звонки в конце: T.get и T::get? - person intrixius; 05.08.2014
comment
@intrixius Это произошло так давно, я не уверен, что побудило меня использовать нотацию ::, возможно, просто попытка показать, что существует несколько способов доступа к методам. Эти два параметра практически идентичны по поведению, но предпочтительнее использовать точечное обозначение. - person coreyward; 05.08.2014

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

module SomeModule
  module_function
  def param; @param end
  def param= v; @param = v end
end

SomeModule.param
# => nil
SomeModule.param = 1
SomeModule.param
# => 1

Тогда переменная экземпляра @param будет принадлежать модулю SomeModule, который является экземпляром класса Module.

person sawa    schedule 17.04.2011

вы можете установить переменную экземпляра класса в модуле.

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

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

MyModule.var    
=> "this is saved at @var"
person Orlando    schedule 09.01.2012
comment
+1, но я просто подчеркну, что переменные экземпляра класса отличаются от переменных класса. - person Andrew Grimm; 09.01.2012

Вы также можете инициализировать значение в определении модуля:

module MyModule
  class << self
    attr_accessor :my_variable
  end
  self.my_variable = 2 + 2
end

p MyModule.my_variable
person Nakilon    schedule 04.03.2016