【Ruby】メソッドの引数は参照の値渡し?
Ruby勉強中ですが、メソッドの引数の渡し方が意外とわかりにくかったので残します。 基本形。
def sample(num, str) puts num # => 1 puts str # => hello! end num, str = 1, "hello!" sample(num, str) puts num # => 1 puts str # => hello!
Rubyは値渡し
メソッド内で値を書き換えても元の変数は書き換わらない。
def sample(num, str) num, str = 5, "world!" puts num # => 5 puts str # => world! end num, str = 1, "hello!" sample(num, str) puts num # => 1 # 変わらない puts str # => hello! # 変わらない
ただし
破壊的メソッドを実行すると元の変数の値が変わってしまう。これは値渡しといいながらRuby自体は全てがオブジェクトであり、オブジェクトとしてメソッドに引数を渡すためこうなるらしい。
def sample(num, str) str.upcase! puts num # => 1 puts str # => HELLO! end num, str = 1, "hello!" sample(num, str) puts num # => 1 puts str # => HELLO! # 変わった!
メソッドに渡す前と後で、変数の領域は異なるが同じオブジェクトを参照してる。 だから「参照の値渡し」というみたい。ふーん。
HashとかArrayも書き換わってしまう
def sample(nums, strs) nums[:one] = 5 strs[0] = "goodby!" puts nums # => {:one=>5, :two=>2} puts strs # => ["goodby!", "world!"] end nums = {one:1, two:2} strs = ["hello!", "world!"] sample(nums, strs) puts nums # => {:one=>5, :two=>2} # 変わった! puts strs # => ["goodby!", "world!"] # 変わった!
でも変数自体に入れなおした場合は
def sample(nums, strs) nums = {three:3, four:4} strs = ["HELLO!", "WORLD!"] puts nums # => {:three=>3, :four=>4} puts strs # => ["HELLO!", "WORLD!"] end nums = {one:1, two:2} strs = ["hello!", "world!"] sample(nums, strs) puts nums # => {:one=>1, :two=>2} # 変わらない puts strs # => ["hello!", "world!"] # 変わらない
なるほど、そういうことか
def sample(nums, strs) nums = {three:3, four:4} strs = ["HELLO!", "WORLD!"] end
とした時点で引数(変数)の参照先が変わるから、元のオブジェクト参照が切れて影響なくなるんだなー。なるほど、気を付けよう。