如何在 Ruby 中初始化模块的实例变量?

我有一些模块,我想在其中使用实例变量:

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

我还可以调用 init 方法来初始化它们:

def init
@var = 0
end

但这意味着我必须记得一直叫它。

还有更好的办法吗?

75512 次浏览

You can use:

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

And it will default to 0 if you don't pass anything.

If you don't want to have to call it everytime, you could use something like this:

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


end

for a class, I'd say the following, since the initialize is called whenever you .new a new instance of the class.

def initialize
@var = 0
end

from Practical Ruby:

It goes on to say that a module's initialize will be called if an including class's initialize calls super, but doesn't mention that this is a consequence of how super works everywhere, not special handling for initialize. (Why might one assume initialize gets special handling? Because it gets special handling with respect to visibility. Special cases create confusion.)

Initialize them in the module definition.

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!"

This will set the instance variables when the module is defined. Remember, you can alwasys reopen the module later to add more instance variables and method definitions, or to redefine existing ones:

# 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?"

i answered a similar question, you can set class instance variables doing this

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"

Apparently it's bad form to initialise instance variables in a module in Ruby. (For reasons I don't fully understand, but pertaining to the order in which things are instantiated.)

It seems that best practice is to use accessors with lazy initialisation, like so:

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

Then use var as the getter for @var.