Crear variables de módulo en Ruby

111

¿Hay alguna forma de crear una variable en un módulo en Ruby que se comporte de manera similar a una variable de clase? Lo que quiero decir con esto es que se podría acceder a él sin inicializar una instancia del módulo, pero se puede cambiar (a diferencia de las constantes en los módulos).

Mark Szymanski
fuente

Respuestas:

158

Ruby admite de forma nativa variables de clase en módulos, por lo que puede usar variables de clase directamente, y no algunas variables proxy o pseudo-clase:

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
fuente
5
+1 En realidad, he estado pensando que el término 'variable de clase' es engañoso. Las clases son casos especiales de módulos y las variables de clase se pueden definir en módulos. Deberían llamarse variables de módulo.
sawa
3
@sawa: Es algo engañoso, pero es lo que utiliza sí Ruby: defined?(@@foo) => "class variable".
Andrew Grimm
1
O podrían llamarse campos estáticos. Parece que eso es lo que son.
Peter Ajtai
@coreyward Hey mi error. ¿Por qué la necesidad de dos variables de clase '@@'? ¿No se considera un olor a código, especialmente si la clase se extiende para usar variables de clase? Estaba probando esto y me di cuenta de que podía obtener el mismo resultado de una sola @variable de instancia. ¿Existe una razón específica para usar variables de clase? Gracias por la respuesta.
fabbb
2
¿Por qué las diferentes llamadas al final: T.gety T::get?
intrixius
31

Si no necesita llamarlo desde dentro de una instancia, simplemente puede usar una variable de instancia dentro del cuerpo del 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

La variable de instancia @parampertenecerá al módulo SomeModule, que es una instancia de la Moduleclase.

sawa
fuente
23

puede establecer una variable de instancia de clase en el 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
fuente
+1, pero solo enfatizaré que las variables de instancia de clase son diferentes a las variables de clase.
Andrew Grimm
4
sí, totalmente ... y por cierto ... no recomiendo usar variables de clase en absoluto ... algunas cosas inesperadas suceden cuando las usas ... revisa este artículo para ver algunos ejemplos oreillynet.com/ruby/blog/2007/01/…
Orlando
8

También puede inicializar el valor dentro de la definición del módulo:

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

p MyModule.my_variable
Nakilon
fuente