Comment puis-je initialiser les variables d’instance d’un module dans Ruby?

J’ai des modules où je voudrais utiliser des variables d’instance. Je les initialise actuellement comme ceci:

module MyModule def self.method_a(param) @var ||= 0 # other logic goes here end end 

Je pourrais aussi appeler une méthode init pour les initialiser:

 def init @var = 0 end 

mais cela voudrait dire que je dois me rappeler de toujours l’appeler.

Existe-t-il une meilleure façon de le faire?

Initialisez-les dans la définition du module.

 module MyModule # self here is MyModule @species = "frog" @color = "red polka-dotted" @log = [] def self.log(msg) # self here is still MyModule, so the instance variables are still available @log < < msg end def self.show_log puts @log.map { |m| "A #@color #@species says #{m.inspect}" } end end MyModule.log "I like cheese." MyModule.log "There's no mop!" MyModule.show_log #=> A red polka-dotted frog says "I like cheese." # A red polka-dotted frog says "There's no mop!" 

Cela va définir les variables d’instance lorsque le module est défini. Rappelez-vous, vous pouvez toujours rouvrir le module plus tard pour append plus de variables d’instance et de définitions de méthodes, ou pour redéfinir les existantes:

 # continued from above... module MyModule @verb = "shouts" def self.show_log puts @log.map { |m| "A #@color #@species #@verb #{m.inspect}" } end end MyModule.log "What's going on?" MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese." # A red polka-dotted frog shouts "There's no mop!" # A red polka-dotted frog shouts "What's going on?" 

Vous pouvez utiliser:

 def init(var=0) @var = var end 

Et il sera par défaut à 0 si vous ne passez rien.

Si vous ne voulez pas avoir à l’appeler à chaque fois, vous pouvez utiliser quelque chose comme ceci:

 module AppConfiguration mattr_accessor :google_api_key self.google_api_key = "123456789" ... end 

pour une classe, je dirais ce qui suit, puisque l’initialisation est appelée chaque fois que vous .nouvelle une nouvelle instance de la classe.

 def initialize @var = 0 end 

de Rubis Pratique :

Il continue en disant que l’initialisation d’un module sera appelée si une classe d’inclusion initialise les appels super, mais ne mentionne pas que ceci est une conséquence de la façon dont super fonctionne partout, pas de traitement spécial pour l’initialisation. (Pourquoi peut-on supposer que l’initialisation reçoit un traitement spécial? Parce qu’il reçoit un traitement spécial en ce qui concerne la visibilité. Les cas particuliers créent de la confusion.)

J’ai répondu à une question similaire, vous pouvez définir des variables d’instance de classe pour ce faire

 module MyModule class < < self; attr_accessor :var; end end MyModule.var => nil MyModule.var = 'this is saved at @var' => "this is saved at @var" MyModule.var => "this is saved at @var" 

Apparemment, ce n’est pas la bonne façon d’initialiser les variables d’instance dans un module dans Ruby. (Pour des raisons que je ne comprends pas bien, mais relatives à l’ordre dans lequel les choses sont instanciées.)

Il semble que la meilleure pratique consiste à utiliser des accesseurs avec une initialisation lente, comme ceci:

 module MyModule def var @var ||= 0 end end 

Ensuite, utilisez var comme getter pour @var .