Ruby プログラミングを学ぶうえで非常に重要なのが非破壊的メソッドと破壊的メソッドの区別ですよね。
「破壊」だなんて物騒! まるで壊してダメにしてしまうかのような用語ですが,そうではなく,レシーバーであるオブジェクトに変化を与えうるメソッドを「破壊的メソッド」と呼んでいるだけですね。
さて,Ruby の初心者向け記事で
破壊的メソッドとはオブジェクトの内容を変えるメソッドである。
というような説明を非常によく目にします。
どこかのスクールでそう教えてるんでしょうかね?
この記事のテーマは,この言明が果たして正しいのかどうか,ということです。
結論を先に書くと,これは「おおむね正しいが,適切な表現ではない」となります。
何をもってオブジェクトの「内容」とするかで正しいかどうかが違ってきます。
例えば文字列オブジェクトの「内容」とは何でしょうか? やはり,「どんな文字がどう並んでいるか」ですよね,内容って。
そういう意味では,「文字列の内容を変えない破壊的メソッド」は存在します。
以下のコードを見ましょう。
str = "Ruby"
p str.frozen? # => false
str.freeze
p str.frozen? # => true
"Ruby"
という文字列リテラルで文字列オブジェクトを生成し,ローカル変数 str
に代入しました。
そのあと,そのオブジェクトが「凍結されているか」どうかを確認したところ,凍結されていないことが分かりました。
「凍結されている」というのは,オブジェクトに変化を与えることができない,という意味です。
次に,そのオブジェクトの freeze
メソッドを呼びました。
このメソッドは,オブジェクトを凍結するメソッドです。
そのあと再び「凍結されているか」を確認すると,凍結されていました。
freeze
メソッドによって文字列オブジェクトの「状態」が変化しました。つまり,freeze
は破壊的メソッドです。
しかし,上述の意味での「文字列の内容」は変更していません。
こんなふうに,「オブジェクトの内容を変更しないがオブジェクトに変化を与える」メソッドは他にもあります。
ハッシュのデフォルト値を変更する Hash#default= なんかもそうですね。デフォルト値を変えたところで,要素(キー/バリューのペア)が変わるわけではありません。「存在しないキーでアクセスしたときの値」が変わるだけです。
これが,冒頭で掲げた言明を「適切な表現ではない」とする根拠です。
しかし,もちろん
ハッシュのデフォルト値も「内容」だ。オブジェクトの凍結状態も「内容」だ。
とする立場もあるでしょう。この場合,冒頭の言明は正しいことになります。しかし,少なくとも誤解を生じやすいとは言えるかと思います。私はああいう表現を避けますね。