Rubyのインスタンス変数について

Rubyの特徴としてよく言われるのは「すべてがオブジェクト」だが、オブジェクトであるならばインスタンス変数を持つことができる。今回はRubyインスタンス変数についての色々。

インスタンス変数とは

Rubyでは「@」ひとつで始まる変数名が自動的にインスタンス変数になる。インスタンス変数はその時点のselfに保存されるので、ローカル変数と違ってコードのどの場所からでも同じselfでさえあれば同じ変数を参照することができる。
通常であればクラスを定義してインスタンスメソッド内で使うことになる。

class Hoge
  def initialize(fuga)
    @piyo = fuga
  end

  def piyo
    @piyo
  end
end

foo = Hoge.new(1)
bar = Hoge.new(2)

p foo.piyo #=> 1
p bar.piyo #=> 2

このコードでは@piyoが参照されるのはselfがHogeオブジェクトの時なので、Hogeオブジェクトに値が保存される。Hogeオブジェクトを複数作るとそれぞれ違う変数になって、違う値を保持することができる。
存在しないインスタンス変数を参照するとnilが返る。

class Hoge
  def initialize(fuga)
    @piyo = fuga
  end

  def piyo
    @piyopiyo
  end
end

foo = Hoge.new(1)
p foo.piyo #=> nil

トップレベルのインスタンス変数

CRubyではトップレベルのselfはmainという名前のオブジェクトである。他の実装については知らない。

p self #=> main

selfがあるのならそこにインスタンス変数を作ることができる。

@piyo = "A"
p @piyo #=> "A"

トップレベルで定義したインスタンス変数はselfがmainのときに使えるので、トップレベルのメソッドの中からでも参照できる。

def foo
  @piyo
end

@piyo = 5
p foo #=> 5

ちょっとした書き捨てスクリプトを作るときに便利かもしれない。

モジュールのインスタンス変数

モジュールもオブジェクトなのでインスタンス変数を作ることができる。モジュールがselfのときに参照することができるので、モジュール直下のコードと、モジュールメソッド内で参照できる。

module Hoge
  @foo = 10

  def self.piyo
    @foo
  end
end

p Hoge.piyo #=> 10

モジュールを定義するとそのモジュールは当然コード内にひとつしかないので、これはsingletonのオブジェクトそのものである。singletonパターンなんかいらんかったんやー(暴言

クラス変数について

似たような見た目の変数でちょっと違うものにクラス変数がある。「@@」で始まる変数名がそれだ。クラス変数はselfではなくselfが所属するクラスに保持される。selfがクラスの場合は自分自身となる。

class Hoge
  @@piyo = 10

  def fuga
    @@piyo
  end
end

foo = Hoge.new
bar = Hoge.new

p foo.fuga #=> 10
p bar.fuga #=> 10

アクセスするときにクラス変数が無い場合はスーパークラスを見にいき、一番上まで行っても無ければ無いということになる。値を読むときに無ければ例外になり、書くときに無ければ最も近いところに保存される。
このような動作のため、クラス変数をスーパークラスとサブクラスの両方で参照する場合はクラス変数を生成するタイミングに気をつけないとハマることになる。

おしまい

別に面白いネタでもなかったのでオチは無い。
以上である。