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

111

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

Марк Шимански
источник

Ответы:

159

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"
Коривард
источник
5
+1 На самом деле, я думал, что термин «переменная класса» вводит в заблуждение. Классы являются частными случаями модулей, а переменные классов могут быть определены в модулях. Их следует называть переменными модуля.
sawa
3
@sawa: Это несколько вводит в заблуждение, но это то , что использует сам Ruby: defined?(@@foo) => "class variable".
Эндрю Гримм
1
Или их можно было бы назвать статическими полями. Кажется, они такие.
Peter Ajtai
@coreyward Привет, моя ошибка. Зачем нужны две переменные класса @@? Разве это не считается запахом кода, особенно если класс расширен для использования переменных класса? Я тестировал это и понял, что могу получить тот же результат от одной @переменной экземпляра. Есть ли конкретная причина для использования переменных класса? Спасибо за ответ.
fabbb
2
почему разные звонки в конце: T.getи T::get?
intrixius 05
31

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

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класса.

Савва
источник
23

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

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

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

MyModule.var    
=> "this is saved at @var"
Орландо
источник
+1, но я просто подчеркну, что переменные экземпляра класса отличаются от переменных класса.
Эндрю Гримм
4
да, полностью ... и кстати ... я вообще не рекомендую использовать переменные класса ... при их использовании происходят неожиданные вещи ... посмотрите эту статью, чтобы увидеть несколько примеров oreillynet.com/ruby/blog/2007/01/ ...
Орландо
8

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

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

p MyModule.my_variable
Nakilon
источник