【问题标题】:How can I initialize a module's instance variables in Ruby?如何在 Ruby 中初始化模块的实例变量?
【发布时间】:2010-10-16 10:42:18
【问题描述】:

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

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

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

def init
  @var = 0
end

但这意味着我必须记住总是调用它。

有更好的方法吗?

【问题讨论】:

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

标签: ruby module instance-variables


【解决方案1】:

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

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

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

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

【讨论】:

  • 已经有一段时间了,但是是的:)。另外,我觉得关于 Messrs Foo 和 Bar 需要说的都已经说完了。
  • 那么此时,不是实例变量,而是实例方法?
  • nipponese:什么不是实例变量?
【解决方案2】:

你可以使用:

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

如果你什么都不通过,它将默认为 0。

如果你不想每次都调用它,你可以使用这样的东西:

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

end

【讨论】:

  • 那么,在对模块进行任何操作之前,我还需要调用这个函数吗?
  • 我添加了第二种方法来避免这个问题 - 它来自 Rails 代码
【解决方案3】:

我回答了一个类似的question,你可以设置类实例变量这样做

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"

【讨论】:

    【解决方案4】:

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

    似乎最好的做法是使用延迟初始化的访问器,如下所示:

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

    然后使用var 作为@var 的getter。

    【讨论】:

    • 请注意,这绝不允许您将@var 设置为nilfalse
    【解决方案5】:

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

    def initialize
       @var = 0
    end
    

    来自Practical Ruby

    接着说一个模块的 初始化将被调用,如果 包括类的初始化调用 超级,但没有提到这个 是 super 工作方式的结果 无处不在,无需特殊处理 初始化。 (为什么有人会假设 初始化得到特殊处理? 因为它得到特殊处理 尊重可见性。特别案例 造成混乱。)

    【讨论】:

    • 既然是模块,那么初始化会被调用吗?这就是我的第一个答案。我添加了第二个以说明它没有被调用。
    • OP 特别提到了模块,而不是类
    猜你喜欢
    • 2011-06-21
    • 2017-04-05
    • 1970-01-01
    • 2014-09-14
    • 2010-10-01
    • 2011-12-25
    • 2017-10-23
    • 1970-01-01
    • 2012-09-17
    相关资源
    最近更新 更多