Crie variáveis ​​de módulo em Ruby

111

Existe alguma maneira de criar uma variável em um módulo em Ruby que se comportaria de forma semelhante a uma variável de classe? O que quero dizer com isso é que ele poderia ser acessado sem inicializar uma instância do módulo, mas pode ser alterado (ao contrário das constantes nos módulos).

Mark Szymanski
fonte

Respostas:

158

Ruby oferece suporte nativo a variáveis ​​de classe em módulos, então você pode usar variáveis ​​de classe diretamente, e não algum proxy ou variáveis ​​de pseudo-classe:

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"
Coreyward
fonte
5
1 Na verdade, tenho pensado que o termo 'variável de classe' é enganoso. As classes são casos especiais de módulos e as variáveis ​​de classe podem ser definidas nos módulos. Eles devem ser chamados de variáveis ​​de módulo.
sawa
3
@sawa: É um pouco enganador, mas é o que o próprio Ruby usa: defined?(@@foo) => "class variable".
Andrew Grimm
1
Ou eles podem ser chamados de campos estáticos. Parece que eles são.
Peter Ajtai
@coreyward Ei, meu erro. Por que a necessidade de duas variáveis ​​de classe '@@'? Não é considerado um cheiro de código, especialmente se a classe for estendida para usar variáveis ​​de classe? Eu estava testando isso e percebi que poderia obter o mesmo resultado de uma única @variável de instância. Existe uma razão específica para usar variáveis ​​de classe? Obrigado pela resposta.
fabbb
2
por que as diferentes chamadas no final: T.gete T::get?
intrixius
31

Se você não precisa chamá-lo de dentro de uma instância, você pode simplesmente usar uma variável de instância dentro do corpo do módulo.

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

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

A variável de instância @paramentão pertencerá ao módulo SomeModule, que é uma instância da Moduleclasse.

sawa
fonte
23

você pode definir uma variável de instância de classe no módulo.

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

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

MyModule.var    
=> "this is saved at @var"
Orlando
fonte
+1, mas vou apenas enfatizar que as variáveis ​​de instância de classe são diferentes das variáveis ​​de classe.
Andrew Grimm
4
sim, totalmente .. e btw .. eu não recomendo usar variáveis ​​de classe .. algumas coisas inesperadas acontecem quando você as usa .. verifique este artigo para ver alguns exemplos oreillynet.com/ruby/blog/2007/01/…
Orlando
8

Você também pode inicializar o valor na definição do módulo:

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

p MyModule.my_variable
Nakilon
fonte