Ruby 破壊的メソッドについて詳しく教えてください。
解決済
回答 4
投稿
- 評価
- クリップ 5
- VIEW 9,310
学習していると、破壊的メソッドという言葉がでてきました。
普通のメソッドはわかるのですが、破壊的メソッドの意味がさっぱりわかりません。
自身の内容を変更するメソッドとは一体なんですか?
これだけで初心者はわかりませんので、どなたか詳しく教えてください。
宜しくお願いします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+3
例えば、文字列には末尾の文字を削る
chop
とその破壊的メソッド chop!
があり、chop!
だけオブジェクトが変更されます。
a = "bar"
p a.chop # "ba"
p a # "bar" : 変わらない
p a.chop! # "ba"
p a # "ba" : 変わる
分かりづらい原因は破壊的メソッドを特別扱いしてる点にあると思います。なぜ特別扱いしているかというと破壊的メソッドは使うべきではない からです。使うべきじゃないので、呼び方も強い感じになっています。
破壊的メソッドを使うべきではない理由はいくつかあるのですが、その一つを説明します。
次の結果は、少しビックリするような結果ではないでしょうか。
b = a = "bar"
a.chop!
p a # "ba"
p b # "ba" : b も変わっている
これは a, b の変数が同じオブジェクトを指しているからなのですが、分かりづらいし、間違いやすくなります。
なので、注意が必要ということで
!
がついて目立つようになっています。
これを破壊的メソッド使わないように書き換えると少し自然な感じになります。
b = a = "bar"
a = a.chop # a が指している先を変える
p a # "ba"
p b # "bar" : b は変わらない
配列の
push
のように破壊的だけど !
がついていないメソッドもあります。こういうメソッドは使わないと不便なものが多いです。
Ruby では $ や @ のように「使うべきではないものはないものは汚く見せる」という方針があります。
!
は使わない方がいいというサインとも言えます。
分かりづらいのであれば、とりあえず破壊メソッドの存在を忘れるというのも手だと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
破壊的メソッドの意味はそのとおりです。
しかし、大事なことは、他の変数の参照先にも影響します。
確かに初心者の方は、これだけではわかりずらいかもしれませんね。
なるべく詳しく、わかりやすく説明します。
例えば以下のサンプルだとわかるのではないかと思いますので、
よくプログラムを読んでみてください。
hennsuu1 = "hennsuu1"
hennsuu2 = hennsuu1 #ここでhensuu1とhennsuu2は同じ文字列"hennsuu1"を参照したことになります。
#ここで破壊的メソッドを理解していただくため
#chopメソッド(末尾1文字を取り除くメソッド)を使って説明します。
p hennsuu1.chop # "hennsuu":hennsuu1の参照先は変更されません。
p hennsuu2 # "hennsuu1"
#ここからが破壊的メソッドです。
p hennsuu1.chop! # "hennsuu": hennsuu1の参照先の変更です。
p hennsuu2 # "hennsuu"
chop!メソッドによって、hennsuu2の参照先に影響を与えています。
これで破壊的メソッドの意味・動きが理解できたのではないかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
この記事の最後に破壊的メソッドについて、簡単にまとめられています。
憶えるべき破壊的メソッドの数は、それほど多くはありません。
とりあえず憶えておくと良い破壊的メソッドの条件を示してみます。
末尾に "!" が付いているメソッド。
リスト的な構造を持つクラスにおいて、 特定の要素を追加・削除・変更するメソッド。
オブジェクトそのものを置き換えたり、消去したり、 属性を変更したりするメソッド。
他の言語での破壊的な動作の一つは インクリメンタル演算 (i++ みたいなもの)
ですが、ruby にはインクリメンタル演算はありません。
- Rubyにインクリメンタル演算子がない理由は?
- Rubyにはイテレータが豊富にあり困らないため、インクリメント演算子やデクリメント演算子が実装されていません。 どうしても必要な場合は、"i = i+1"としたり下記のサンプルのようにnextメソッドやsuccメソッドを使用します。
といった記事も読むと良いとおもいます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
非破壊的メソッド(破壊的メソッドでないメソッド)=レシーバーのオブジェクトを書き換えないメソッド。必要ならコピーして処理される
というような説明が多分入門書に書いてあったと思うのですが、それがわかりにくいと言うことですよね。
たとえ話で説明します。
紙に文字が書いてあったとします。それを修正した物が欲しいときに、
・その紙に書き加えたり、消しゴムで消したりして修正する方法⇒破壊的メソッド
・その紙はそのままにして、別の紙を買ってきて、新しい紙に古い紙を見ながら修正後の文字を書く方法⇒非破壊的メソッド
どちらが良い悪いではなくて、目的によって使い分けます。
違いが出てくる一つは、(他の回答者がプログラムの例で説明していますが)別の人が最初の紙をじっと見ている場合ですね。
元の紙を書き換えると、その紙を見つめている他の人にも変更が伝わります。
別の買ってきた紙に書き込むと、元の紙を見ていた人に新しい紙に書かれたことが伝わりません。
これのどちらが良いのかは、その処理をどういう目的でするかによります。
違いのもう一つは、処理効率です。
紙に100万文字書いてあったとします。その紙の末尾の1文字を消すのと、別の紙に99万9999文字書き写すのとどちらが早いと思いますか?そもそも別の紙を用意するのにも処理コストがかかります。
まあ、「Rubyで書くのに細かい効率を気にするな」と言うのはあるかもしれませんが。
また、破壊的メソッドは ! が付いている物だけではありません。Stringの場合にメソッド一覧から ! の付かない破壊的メソッドを拾ってみると、見落としがあるかもですが、これだけあります。
<<,[]=,concat,clear,force_encoding,insert,prepend,replace,setbyte
この中には、
a << b ⇒ a += b
のように同じような処理をする非破壊的メソッドがある場合もあります。
String以外のクラスでも ! の付かない破壊的メソッドはいろいろあります。
関連した話としては、紙の表面にコーティングしたようにして、その紙の内容を変更不可能にする事もできます。
a.freeze とすると(凍らせるということですね)、aのオブジェクトに対して破壊的メソッドは全部エラーになります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
同じタグがついた質問を見る
関連ワード: ruby 破壊的メソッド
2014/09/01 11:40