入社3年目にして早くも自分の勤続年数を忘れてきている金子です。
今回は、初めてRubyを使ったお仕事をした時にハマってしまったので、
その経験をもとに、破壊的メソッドの注意点についてお話ししたいと思います。
破壊的メソッドとは
まずは破壊的メソッドについて簡単に説明します。
破壊的メソッドとは、実行した時にレシーバのオブジェクト自身の内容を変更してしまうメソッドのことです。
Rubyではメソッド名の最後が「!」になっているものが多いです。
(Array#delete_ifなど、名前に「!」が付いていない破壊的メソッドもあります)
例として、gsub!(破壊的メソッド)とgsub(そうでないメソッド)の動きの違いを、irbコマンドを用いて確認してみます。
ちなみにgsubメソッドは、第一引数の文字列を第二引数の文字列に置換するメソッドです。
1
2
3
4
5
6
7
8
9
10
|
irb(main):002:0> str = "こんにちは"
=> "こんにちは"
irb(main):006:0> str.gsub("にちは", "ばんは")# 通常のgsub
=> "こんばんは"
irb(main):008:0> str# str自体の値は変更されていない
=> "こんにちは"
irb(main):010:0> str.gsub!("にちは", "ばんは")# 破壊的メソッドgsub!
=> "こんばんは"
irb(main):012:0> str# strの値も変更される
=> "こんばんは"
|
上記の結果を見ると、gsubの方は実行後も変数strの値が変わっていませんが、
gsub!の方は実行後にstrの値も変更されていることがわかります。
メソッドチェーン内で破壊的メソッドを使用すると…
ここで、メソッドチェーンの中で破壊的メソッドを使用してみます。
以下の例では、数値をto_sメソッドで文字列に変換してから、破壊的メソッドgsub!を実行しています。
1
2
3
4
5
6
|
irb(main):019:0> num = 10101
=> 10101
irb(main):025:0> num.to_s.gsub!("0", "")
=> "111"
irb(main):028:0> num
=> 10101
|
すると、gsub!を実行したにもかかわらず、numの値は変わっていないことがわかります。
上記の場合gsub!のレシーバはあくまでto_sであるため、変数numの値には影響がないのです。
そのためnumの値を変更したい場合は、一度numを文字列に変換した上でgsub!を実行するか、
gsub!の返却値を再度numに代入するしかありません。
(後者の場合だと破壊的メソッドを使用する意味はありませんが)
よくよく考えればわかることですが、はじめてRubyを扱ったときはかなりハマってしまいました。
メソッドチェーンには気をつけましょう!