Rubyのクラス変数(@@var)の挙動を学ぶ
Rubysilvar取得に向けて学習をしているのですが、クラス変数の挙動でつまづいたので
-
@@varがどこまで共有されるのか? - Foo と Bar(継承関係)で値はどう変化する?
- 出力結果はどうなる?
という点をまとめます。
問題のコード
class Foo
@@var = 0
def var
@@var
end
def var=(value)
@@var = value
end
end
class Bar < Foo
end
foo = Foo.new
foo.var += 1
bar = Bar.new
bar.var += 2
puts "#{foo.var}/#{bar.var}"
上記は3/3
Rubyのクラス変数(@@var)はクラス階層で1つだけ共有
Rubyの@@varは、**そのクラスとサブクラス全体で"1つだけ"共有される。
- Foo のインスタンス
- Bar(Foo のサブクラス)のインスタンス
すべてが同じ@@varを参照
処理の流れ
①最初の状態
@@var = 0
②fooの処理
foo = Foo.new
foo.var += 1
内部的にはこう動く
-
foo.var→@@varを読み出す(0) @@var = 0 + 1
結果
@@var = 1
③barの処理
BarはFooを継承している。同じクラス変数を共有する。
bar = Bar.new
bar.var += 2
内部的には
-
bar.var→ 現在の@@var(1) @@var = 1 + 2
結果
@@var = 3
④出力
puts "#{foo.var}/#{bar.var}"
どちらも同じ@@varを読みにいく
3/3
となる。
なぜ1/2ではないのか?
直感的に「Fooは1、Barは2」になると思ったけども、クラス変数はインスタンスごとではなく"クラス階層全体で1つのため、
- Fooが変更 → Barでも変更済みの値が見える
- Barが変更 → Fooからも同じ値が見える
という挙動になる。
まとめ
-
@@varはクラス階層全体で共有される - FooもBarも同じ1つの変数を見ている
- よって出力は 3/3
初学者のため、間違えていたらすいません。