この動作は正しいですか? 次のようなコードを実行しています。
@a_hash = {:a => 1}
x = @a_hash
x.merge!({:b => 2})
すべての最後に、x の値は期待どおりに変更されましたが、@a_hash の値も変更されました。両方の値として {:a => 1, :b => 2} を取得しています。これはRubyの通常の動作ですか?
この動作は正しいですか? 次のようなコードを実行しています。
@a_hash = {:a => 1}
x = @a_hash
x.merge!({:b => 2})
すべての最後に、x の値は期待どおりに変更されましたが、@a_hash の値も変更されました。両方の値として {:a => 1, :b => 2} を取得しています。これはRubyの通常の動作ですか?
はい、インスタンス変数@a_hash
とローカル変数は同じインスタンスへの参照x
を格納します。このインスタンスを変更すると (オブジェクトを変更する mutator メソッドを使用して)、これらの変数は同じ値に評価されます。Hash
merge!
merge
オブジェクトのコピーを作成し、元のオブジェクトを変更しないメソッドを使用することができます。
@a_hash = {:a => 1}
x = @a_hash
y = x.merge({:b => 2})
# y => {:a => 1, :b => 2}
# x and @a_hash => {:a => 1}
@a_hash は x へのリンクです。したがって、@a_hash を変更したくない場合は、次のようにする必要があります。
@a_hash = {:a => 1}
x = @a_hash.clone
x.merge!({:b => 2})
はい、これは ruby (および他のほとんどの言語) での通常の動作です。x
とはどちらも@a_hash
同じオブジェクトへの参照です。呼び出すmerge!
ことで、そのオブジェクトを変更し、それを参照するすべての変数を通じてその変更を可視化できます。
その動作を望まない場合は、変更メソッドを使用しない (x = x.merge(...)
代わりに使用する) か、変更する前にオブジェクトをコピーする (つまりx = @a_hash.dup
) 必要があります。