J'ai certains modules dans lesquels j'aimerais 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 également appeler une méthode init pour les initialiser:
def init
@var = 0
end
mais cela signifierait 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 définira les variables d'instance lorsque le module est défini. N'oubliez pas que vous pouvez toujours rouvrir le module ultérieurement pour ajouter d'autres variables d'instance et définitions de méthode, ou pour redéfinir celles 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 .new une nouvelle instance de la classe.
def initialize
@var = 0
end
de Ruby pratique :
Il continue en disant que l'initialisation d'un module sera appelée si l'initialisation d'une classe incluant appelle super, mais ne mentionne pas que c'est une conséquence de la façon dont super fonctionne partout, pas une gestion spéciale pour l'initialisation. (Pourquoi pourrait-on supposer que l'initialisation reçoit un traitement spécial? Parce qu'il obtient un traitement spécial en ce qui concerne la visibilité. Les cas spéciaux créent de la confusion.)
j'ai répondu à une --- question similaire, vous pouvez définir les variables d'instance de classe en faisant cela
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, c'est une mauvaise forme d'initialiser des variables d'instance dans un module de Ruby. (Pour des raisons que je ne comprends pas bien, mais concernant l'ordre dans lequel les choses sont instanciées.)
Il semble que la meilleure pratique consiste à utiliser des accesseurs avec une initialisation paresseuse, comme ceci:
module MyModule
def var
@var ||= 0
end
end
Utilisez ensuite var
comme getter pour @var
.