はじめに
Rubyは値を代入するのではなく、実際に値が保存されているメモリの場所を代入しています。(参照渡し)
PHPとかだと普通は値渡しで代入されるので、Rubyを使っていて混乱したのでまとめます。
ハッシュを使い回して変数に代入してみる
検証コード
reports = {}
#----------------------
reports["subject"] = "Math"
reports["score"] = 60
str_math = reports
reports["subject"] = "English"
reports["score"] = 20
str_english = reports
#----------------------
puts str_math #{"subject"=>"Math", "score"=>60}となるはず
puts str_english #{"subject"=>"English", "score"=>20}となるはず
実行結果
{"subject"=>"English", "score"=>20}
{"subject"=>"English", "score"=>20}
なぜハッシュや配列の使い回し・再利用で値が上書きされるのか
上記の検証コードに、対象のオブジェクト(ハッシュ・変数)に割り当てられているメモリの場所的なものを表示する処理を追加して、動きを確認してみます。(正確には、Rubyがオブジェクトに割り当てている整数値を返します。)
object_idを表示するよう変更して再検証
reports = {}
puts reports.object_id
puts "----------------------"
reports["subject"] = "Math"
reports["score"] = 60
str_math = reports
puts str_math
puts str_math.object_id
reports["subject"] = "English"
reports["score"] = 20
str_english = reports
puts str_english
puts str_english.object_id
puts "----------------------"
puts str_math ###{"subject"=>"Math", "score"=>60}となるはず
puts str_english ###{"subject"=>"English", "score"=>20}となるはず
再検証の実行結果
7815320
----------------------
{"subject"=>"Math", "score"=>60}
7815320
{"subject"=>"English", "score"=>20}
7815320
----------------------
{"subject"=>"English", "score"=>20}
{"subject"=>"English", "score"=>20}
解説
reports.object_id や str_math.object_id のようにobject_idを出力しています。
reports、str_math、str_englishそれぞれでobject_idを出力していますが、どれも「7815320」で共通していますね。つまり、三つともすべて同じ場所を参照していることを意味します。
拙い図ですが…
図1のように値が変数に代入されるのではなく、

図2のように値が入っているメモリの場所を代入しているというわけです。

コメント