Ruby を書いていると必ず出てくる3種類の変数。
-
インスタンス変数(@var)
-
クラス変数(@@var)
-
クラスインスタンス変数(@var を class << self 内で使う)
この3つ、名前が似ているのに挙動が全然違うので混乱しやすい。
この記事では、それぞれの特徴を 例文+解説+比較表 で一気に理解できるようにまとめる。
1. インスタンス変数(@var)
特徴
インスタンスごとに別々の値を持つ
最もよく使う!
オブジェクトの状態を表す
例文
class User
def initialize(name)
@name = name
end
def name
@name
end
end
u1 = User.new("Airi")
u2 = User.new("Mika")
puts u1.name # => Airi
puts u2.name # => Mika
解説
@name は インスタンスごとに独立しているので、
u1 と u2 は別々の値を持つ。
2. クラス変数(@@var)
特徴
クラス階層全体で共有される
親クラス・子クラス・インスタンス全部で同じ値
Ruby の中でもクセが強く、非推奨気味
例文
class Foo
@@count = 0
def add
@@count += 1
end
def count
@@count
end
end
class Bar < Foo
end
f = Foo.new
b = Bar.new
f.add # @@count = 1
b.add # @@count = 2
puts f.count # => 2
puts b.count # => 2
解説
@@count は Foo と Bar で共有されるため、
どこで更新しても同じ値になる。
3. クラスインスタンス変数(@var in class << self)
特徴
クラスごとに独立した値を持つ
クラス変数と違い、継承しても共有されない!
実務ではこれが最も安全で推奨されるらしい!
例文
class Foo
class << self
@count = 0
attr_accessor :count
end
end
class Bar < Foo
class << self
@count = 0
attr_accessor :count # 各クラスで明示的に定義
end
end
Foo.count += 1
Bar.count += 5
puts Foo.count # => 1
puts Bar.count # => 5
解説
Foo の @count と
Bar の @count は
完全に別物。
クラス変数(@@)とは違い、継承しても混ざらない!
まとめ比較表
| 種類 | 記法 | 共有範囲 | 挙動 | よく使う場面 |
|---|---|---|---|---|
| インスタンス変数 | @var | インスタンスごと | 独立 | オブジェクトの状態 |
| クラス変数 | @@var | クラス階層全体 | 共有 | ほぼ非推奨 |
| クラスインスタンス変数 | @var(class << self) | クラスごと | 独立 | 設定値・カウンタ |
実務で使うべきはこれ!!!
-
インスタンス変数 → ほぼ必須
-
クラスインスタンス変数 → クラスごとの設定値に最適
-
クラス変数 → ほぼ使わない方がいい(バグの温床)