受講料が最大70%OFF 受講料が最大70%OFF

Rubyで配列やハッシュなどのオブジェクトのコピーを利用したいなら、=演算子ではなく、dupメソッドを使ってください。

Rubyのオブジェクトのコピーは、他のプログラム言語とは違います。dupメソッドを知らないと、知らずに不具合を作ってしまうかもしれません。今回は、dupメソッドのことをよく知らない方のために、例を使って詳しく解説します。

Rubyでオブジェクトをコピーするには

Rubyで配列やハッシュなどのオブジェクトをコピーする場合、別の変数名で参照できる方法と、同じ内容を複製する方法の2つが使えます。具体的に前者は、「=」でオブジェクトをコピーした場合で、後者はdupメソッドまたはcloneメソッドを使った場合です。

dupメソッドおよびcloneメソッドを解説する前に、Rubyにおけるオブジェクトのコピーについて説明します。

=演算子でオブジェクトをコピーした場合

C言語を学んだ方なら、変数をコピーする場合、あらかじめコピーしたデータを格納するためのメモリ領域を確保してから、コピーすることをご存じでしょう。しかし、Rubyでは、変数の宣言やメモリの確保といった処理が自動化されており、プログラマーが変数の領域を意識しなくてもプログラムを作成できます。

そして、Rubyでは、オブジェクトのコピーに=演算子を使用した場合、コピー元と全く同じものが別に作られる訳ではありません。コピー元の参照する新しいラベルが作られると考えてください。

=演算子で配列をコピーした例

a = [1, 2, 3]
b = a
p a # [1, 2, 3]が表示される
p b # [1, 2, 3]が表示される
a[0] = 10
p a # [10, 2, 3]が表示される
p b # [10, 2, 3]が表示される

この例は、配列aを、=演算子でbにコピーした例です。この場合、bの内容はaと同じなので、途中でa[0]を書き換えると、b[0]も変わってしまいます。

dupメソッドでコピーした場合

先ほど、Rubyの=演算子でオブジェクトをコピーした場合の例を紹介しましたが、複製を作成する場合にはdupメソッドを使います。そして、dupメソッドを利用した場合、先ほどの例のように、コピー元のオブジェクトを書き換えると、コピー先も変わる、ということはありません。

dupメソッドで配列をコピーした例

a = [1, 2, 3]
b = a.dup
p a # [1, 2, 3]が表示される
p b # [1, 2, 3]が表示される
a[0] = 10
p a # [10. 2. 3]が表示される
p b # [1, 2, 3]が表示される

dupメソッドで複製を作った場合、先ほどの=演算子を使った例のように、配列aのa[0]を書き換えても、b[0]が変わることはありません。

なお、Rubyには、dupメソッドとほぼ同じ機能のcloneメソッドもあり、同じように使うことが可能です。

文字列や変数はどうなる

Rubyのプログラムで扱う変数やメソッドなどは全てオブジェクトの一部です。しかし、先ほどのように、全てのオブジェクトで=演算子を使うと、新しいラベルが追加される、という訳ではありません。

例えば、数字を格納する変数をコピーすると、その複製が作成されます。コピー先を修正しても、元の変数の数字が書き換わることはありません。また、文字列も同じです。

dupメソッドやcloneメソッドが使えるオブジェクトと不要なオブジェクトがあることを理解して、うまく=演算子と使い分けられるようになりましょう。

dupメソッドの基本

先ほど説明したように、Rubyではオブジェクトの複製を作成するdupメソッドが使えます。次から、dupメソッドの文法と基本的な使い方を解説します。

dupメソッドの文法

dupメソッドは、オブジェクトの複製を返すメソッドです。また、メソッド単体で使用し、引数やブロック構文はありません。

オブジェクト.dup

dupメソッドを使った簡単な例

a = [1, 2, 3]
b = a.dup
p a # [1, 2. 3]が表示される
p b # [1, 2, 3]が表示される

cloneメソッドの基礎

先ほど説明したdupメソッドと同じ機能のメソッドとして、cloneメソッドも利用できます。ただし、cloneメソッドは、dupメソッドと同じではありません。次に、cloneメソッドの基本について説明します。

cloneメソッドの文法

cloneメソッドは、先ほど説明したdupメソッドと同じくオブジェクトの複製を返すメソッドで、freezeを含めて複製できます。

なお、freezeとは、オブジェクトの内容を禁止するfreezeメソッドを適用した状態で、この状態のオブジェクトは変更できません。cloneは、freeze状態もいっしょにコピーします。

オブジェクト.clone( freezeの有無 )

freezeの有無を省略した場合は、freeze状態もいっしょにコピーしますが、falseを指定した場合は、freezeをコピーせず、dupを全く同じ機能です。

cloneメソッドの簡単な使用例

a = [1, 2, 3]
a.freeze
b = a.clone
p a # [1, 2. 3]が表示される
p b # [1, 2, 3]が表示される

この場合、配列aはfreezeメソッドが適用されているので、修正できません。そして、cloneメソッドでコピーされた配列bも、freeze状態がいっしょにコピーされているので、修正できなくなっています。

freezeの解除はdupで

オブジェクトをfreeze状態にしてしまうと、そのオブジェクトは修正できません。そして、先ほど説明したように、cloneメソッドでコピーを作成すると、freeze状態もいっしょにコピーされるので、やはり修正できません。

しかし、dupは、freeze状態をコピーしません。freeze状態のオブジェクトをコピーし、その一部を変更した配列を利用する場合は、dupメソッドを活用してください。

なお、オブジェクトがfreeze状態かどうかは、frozen?メソッドでチェックできます。

Railsではdeep_dupが使える

これまで紹介したきたdupメソッドとclonseメソッドを使用して複製を作っても、オブジェクトの参照先まではコピーされません。もし、そこまでのコピーが必要なら、Ruby on Railsのdepp_dupの利用を検討してください。

dupとcloneは浅いコピー

dupメソッドとcloneメソッドでオブジェクトの複製を作成しても、オブジェクトの指している先までは複製されません。これを浅いコピーと言い、逆にオブジェクトの指している先までコピーするケースは、深いコピーと呼びます。

Rubyの標準機能で深いコピーを実現するには、Marshalモジュールで可能ですが、使い易いとは言えません。そのため、dupメソッドと同じようにつかえる、Ruby on Railsのdeep_dupの利用を検討してください。

deep_dupの基本

先ほど説明したように、deep_dupメソッドは、オブジェクトの深いコピーを返します。

オブジェクト.deep_dup

deep_dupを使った例

require 'active_support/all'
hash1 = { a: 'test', b: 2, c: 3 }
hash2 = hash1.deep_dup

今回紹介するdeep_dupメソッドは、Ruby on Railsの機能の一部ですが、active_supportをインストールすることで、Ruby on Rails以外の環境でも利用できます。上の例では、require ‘active_support/all’で、Ruby on Railsの機能を利用し、deep_dupメソッドを使っています。

まとめ

これまで説明したように、Rubyでオブジェクトのコピーを利用する場合、=演算子でコピーしただけでは、十分ではありません。配列やハッシュなどのオブジェクトの複製を作る場合は、dupメソッドまたはcloneメソッドを利用してください。

ただし、dupメソッドやcloneメソッドを使用しても、完全なコピーは作れません。もし、Rubyのプログラムの中で、オブジェクトの完全なコピーを使用する場合は、Ruby on Railsの機能の一部であるdeep_dupを利用する方法もあります。

ぜひ、dupメソッドとcloneメソッドの使い方を理解して、Rubyのプログラムに活かしてください。

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。