web-dev-qa-db-ja.com

Rubyでモジュールのインスタンス変数を初期化するにはどうすればよいですか?

インスタンス変数を使用したいモジュールがいくつかあります。現在、次のように初期化しています:

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

また、initメソッドを呼び出して初期化することもできます。

def init
  @var = 0
end

しかし、これは常にそれを呼び出すことを覚えておく必要があることを意味します。

これを行うより良い方法はありますか?

76
Geo

モジュール定義でそれらを初期化します。

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?"
104
rampion

次を使用できます。

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

何も渡さない場合、デフォルトで0になります。

毎回呼び出す必要がない場合は、次のようなものを使用できます。

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

end
5
Brian

クラスの場合、クラスの新しいインスタンスを作成するたびに初期化が呼び出されるため、次のように言います。

def initialize
   @var = 0
end

from Practical Ruby

さらに、インクルードクラスのinitializeがsuperを呼び出すと、モジュールのinitializeが呼び出されますが、これは初期化の特別な処理ではなく、superがどこでも動作する結果であることは言及していません。 (initializeが可視性に関して特別な処理を取得するため、initializeが特別な処理を取得すると仮定する理由はあります。特別な場合は混乱を生じます。)

2
consumer

私は同様の 質問 に答えました、あなたはこれを行うクラスインスタンス変数を設定することができます

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
Orlando

どうやらRubyのモジュールでインスタンス変数を初期化するのは悪い形です。 (私は完全には理解していませんが、物事がインスタンス化される順序に関するものです。)

ベストプラクティスは、次のように遅延初期化でアクセサーを使用することです。

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

次に、@varのゲッターとしてvarを使用します。

2
Andy