Créer des variables de module dans Ruby

111

Existe-t-il un moyen de créer une variable dans un module de Ruby qui se comporterait de la même manière qu'une variable de classe? Ce que je veux dire par là, c'est qu'il pourrait être accessible sans initialiser une instance du module, mais il peut être modifié (contrairement aux constantes dans les modules).

Mark Szymanski
la source

Réponses:

158

Ruby prend en charge nativement les variables de classe dans les modules, vous pouvez donc utiliser directement des variables de classe, et non des variables proxy ou pseudo-classe-variables:

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
la source
5
+1 En fait, j'ai pensé que le terme «variable de classe» est trompeur. Les classes sont des cas particuliers de modules, et les variables de classe sont définissables sur les modules. Ils devraient être appelés variables de module.
sawa
3
@sawa: Il est un peu trompeur, mais il est ce que Ruby utilise lui - même: defined?(@@foo) => "class variable".
Andrew Grimm
1
Ou ils pourraient être appelés champs statiques. Il semble que c'est ce qu'ils sont.
Peter Ajtai
@coreyward Hé mon erreur. Pourquoi le besoin de deux variables de classe «@@»? N'est-ce pas considéré comme une odeur de code, surtout si la classe est étendue pour utiliser des variables de classe? J'étais en train de tester cela et j'ai réalisé que je pouvais obtenir le même résultat à partir d'une seule @variable d'instance. Y a-t-il une raison spécifique d'utiliser des variables de classe? Merci pour la réponse.
fabbb
2
pourquoi les différents appels à la fin: T.getet T::get?
intrixius
31

Si vous n'avez pas besoin de l'appeler depuis une instance, vous pouvez simplement utiliser une variable d'instance dans le corps du module.

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 d'instance @paramappartiendra alors au module SomeModule, qui est une instance de la Moduleclasse.

Sawa
la source
23

vous pouvez définir une variable d'instance de classe dans le module.

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

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

MyModule.var    
=> "this is saved at @var"
Orlando
la source
+1, mais je soulignerai simplement que les variables d'instance de classe sont différentes des variables de classe.
Andrew Grimm
4
ouais totalement .. et btw .. je ne recommande pas du tout d'utiliser des variables de classe .. des choses inattendues se produisent lorsque vous les utilisez .. consultez cet article pour voir quelques exemples oreillynet.com/ruby/blog/2007/01/…
Orlando
8

Vous pouvez également initialiser la valeur dans la définition du module:

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

p MyModule.my_variable
Nakilon
la source