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


80

我有一些模块要在其中使用实例变量。目前,我正在像这样初始化它们:

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

我也可以调用一个init方法来初始化它们:

def init
  @var = 0
end

但这意味着我必须记住始终调用它。

有更好的方法吗?


3
第一个代码块不是设置模块实例var(在MyModule的类型对象范围内的var),而第二个代码块是否设置“普通”实例var(在包含模块的实例的范围内的var)?我认为这两个代码块做的不一样...
Boris B.

Answers:


109

在模块定义中初始化它们。

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

定义模块时,这将设置实例变量。请记住,您可以稍后alwasys重新打开模块以添加更多实例变量和方法定义,或重新定义现有的变量和方法定义:

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

12
已经有一段时间了,但是:)。另外,我觉得关于Foo和Bar先生的所有事情都已经说了。
抢劫

因此,在这一点上,实例变量不是实例变量吗?
日本,2014年

日本语:什么不是实例变量?

5

您可以使用:

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

如果您不传递任何内容,它将默认为0。

如果您不想每次都调用它,则可以使用以下方法:

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

end

因此,在对模块执行任何操作之前,我仍然需要调用此函数吗?
地理

我添加了第二种方法来避免该问题-从Rails代码中了解
布赖恩(Brian

2

对于一个类,我会说以下内容,因为每当您.new一个新的类实例时,都会调用initialize。

def initialize
   @var = 0
end

来自实用Ruby

继续说,如果包含类的initialize调用super,则将调用模块的initialize,但没有提及这是super在任何地方都起作用的结果,而不是对initialize的特殊处理。(为什么要假设初始化会受到特殊处理?因为它在可见性方面受到特殊处理。特殊情况会造成混淆。)


1
由于它是一个模块,初始化会被调用吗?那就是我的第一个答案。我添加了第二个以说明它没有被调用。
布赖恩2009年

1
OP特别提到了模块,而不是类
Zensaburou

2

我回答了类似的问题,您可以这样做设置类实例变量

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"

2

显然,在Ruby中的模块中初始化实例变量是一种不好的形式。(出于某种原因,我没有完全理解,但与实例化事物的顺序有关。)

似乎最佳实践是使用带有延迟初始化的访问器,如下所示:

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

然后var用作的吸气剂@var


4
请注意,这将永远不允许您将@var设置为nilfalse
steel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.