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


80

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

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

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

def init
  @var = 0
end

しかし、これは私が常にそれを呼ぶことを忘れないことを意味するでしょう。

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


3
最初のコードブロックはモジュールインスタンス変数(MyModuleの型オブジェクトのスコープ内の変数)を設定し、2番目のコードブロックは「プレーン」インスタンス変数(モジュールを含むインスタンスのスコープ内の変数)を設定しませんか?私は...これら2つのコードブロックが同じことをしないと思います
ボリスB.

回答:


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
久しぶりですが、ええ:)。さらに、Messrs Foo andBarについて言わなければならないことはすべて言われていると思います。
暴れ

したがって、この時点では、インスタンス変数ではなく、インスタンスメソッドですか?
nipponese 2014

nipponese:インスタンス変数ではないものですか?
暴れ回る2014

5

次を使用できます。

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

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

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

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

end

それで、モジュールで何かをする前に、この関数を呼び出す必要がありますか?
geo

私はその問題を回避するための2番目の方法を追加しました-それはレールコードからです
ブライアン

2

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

def initialize
   @var = 0
end

実用的なルビーから:

インクルードクラスの初期化がsuperを呼び出すと、モジュールの初期化が呼び出されると言いますが、これは、初期化の特別な処理ではなく、superがあらゆる場所でどのように機能するかの結果であるとは述べていません。(初期化が特別な処理を受けると想定するのはなぜですか?可視性に関して特別な処理を受けるためです。特別な場合は混乱を招きます。)


1
そのモジュールなので、初期化は呼び出されますか?それが私の最初の答えでした。呼び出されないことを説明するために2番目を追加しました。
ブライアン

1
OPはクラスではなくモジュールについて具体的に言及しました
Zensaburou 2016年

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
鋼の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.