0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Ruby】定数や変数を別の変数に代入すると元の変数の値も変更されてしまう

Last updated at Posted at 2023-05-07

はじめに

ある変数を別の変数に代入した後、代入後の変数に変更を加えると、元の変数まで変更が反映されてしまい、初めて知った挙動だったので、流れをまとめてみました。

概要

サンプルコードを以下に記します。
下記のように、クラス内で定義したADRESSという定数を、メソッド内で利用するために、adressという変数に格納しています。

class XXXX
  ADRESS = {"東京都":["中央区","千代田区"],"大阪府":["大阪市","堺市"]}

  def xxx
    adress = ADRESS
    ...
    adress.merge!({"愛知県":["名古屋市","豊田市"]}) ### adressに変更を加える
  end
end

このxxxというメソッドを実行後、各変数の値を確認すると、下記のような結果となりました。
merge!を行ったadress の値が変更されたのは意図通りでしたが、元のADRESSの値まで変更が及んでいました。

puts adress
=> {:東京都=>["中央区", "千代田区"], :大阪府=>["大阪市", "堺市"], :愛知県=>["名古屋市", "豊田市"]}

puts ADRESS
=> {:東京都=>["中央区", "千代田区"], :大阪府=>["大阪市", "堺市"], :愛知県=>["名古屋市", "豊田市"]}

原因

原因について、調べていたところ、ちょうど、下記の記事が参考になりました。

記事の通り、各変数のobject_idを確かめてみると、同じ値を返ってきており、2つの変数が同じオブジェクトを参照していたことがわかりました。

### 同じオブジェクトを参照している
ADRESS.object_id
=> 17420

adress.object_id
=> 17420

このため、adressに変更を加えると、ADRESSにも変更が反映されてしまうということでした。

最後に

結構、長時間嵌ってしまいましたが、オブジェクトの振る舞いが確認できました。
あとは、定数が変化された時、エラーになってくれてたら、すぐ気づけたと思うので、定数の定義には、freezeとかした方がよさそう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?