Rubyのdupとcloneでオブジェクトを複製する方法【初心者向け】

初心者向けにRubyのdupとcloneでオブジェクトを複製する方法について解説しています。オブジェクトのコピーに使われるdupとcloneについて、それぞれの違いと実際の書き方について学んでいきましょう。

TechAcademyマガジンはオンラインのプログラミングスクールTechAcademy [テックアカデミー]が運営する教育×テクノロジーのWebメディアです。初心者でもすぐ勉強できる記事が2,000以上あります。

Ruby で Object をコピーする方法は複数個ありますが、その中で `dup` と `clone` を紹介します。

Rubyについてそもそもよく分からないという方は、Rubyとは何なのか解説した記事をまずご覧ください。

 

なお本記事は、TechAcademyのWebアプリケーションオンラインブートキャンプの内容をもとに紹介しています。

 

田島悠介

今回は、Rubyに関する内容だね!

大石ゆかり

どういう内容でしょうか?

田島悠介

dupとcloneでオブジェクトを複製する方法について詳しく説明していくね!

大石ゆかり

お願いします!

 

dupとcloneの違い

様々な違いがありますが、実際にRubyでコードを書くために必要な知識として覚えておきたいのは2つの違いです。

  1. `clone` は特異メソッド、 `freeze` をコピーする
  2. `dup` は上記2つをコピーしない

それぞれどういったものか紹介します。

特異メソッドというのは、そのObjectしか使えないメソッドのことだ。定義の方法は以下のようにすると定義できます

rb

string = 'hoge'
dummy = 'hoge'

def string.piyo?
  false
end

string.piyo? #=> false
dummy.piyo? #=> NoMethodError

この `piyo?` メソッドは上記コンテクストにおいての `string` Objectでしか利用することができません。

同じ `hoge` 文字列であっても、 `dummy` Objectにはそのようなメソッドが定義されていない、となります。

そして `freeze` はObjectの状態を凍結する目的で利用されます。

rb

class Klass
  attr_accessor :var
end

k = Klass.new
k.var = 'hoge'
puts k.var #=> 'hoge'

k.freeze
k.var = 'piyo' #=> FrozenError: can't modify frozen

このように、 `freeze` されたObjectはその内部状態を変更することができなくなります

さて、ようやくこれでもとの話に戻ると、つまり `clone` は上記のような情報もコピーし、 `dup` ではコピーしません

 

dupとcloneでオブジェクトを複製する方法

実際に複製する方法は行かようなコードとなります。

rb

cloned_object = object.clone
duped_object = object.dup

Objectが持っているメソッドなので、他のメソッド同様に記述し、その返り値がコピーされたObjectとなります。

 

[PR] Rubyのプログラミングで挫折しない学習方法を動画で公開中

実際に書いてみよう

それでは実際に書いてみましょう。

rb

class Klass
attr_accessor :var
end

k = Klass.new
k.var = 'hoge'

def k.piyp?
self.var == 'piyo'
end

k.piyo? #=> false
k.var = 'piyo'
k.piyo? #=> true
k.freeze

cloned_k = k.clone
duped_k = k.dup

puts cloned_k.var #=> 'piyo'
puts cloned_k.piyo? #=> true
puts cloned_k.var = 'huga' #=> FrozenError: can't modify frozen

pust duped_k #=> 'piyo'
puts duped_k.piyo? #=> NoMethodError
puts duped_k.var = 'huga'

puts k.piyo? #=> true
puts k.var = 'huga' #=> FrozenError: can't modify frozen

ではどのような場面でこれが利用できるかというと、もとのObjectの状態を変更せずに、新たなObjectとして同じものを利用したいときなどに活用できます。

特に `irb` などで様々な実験をしたいときなどに、 元のObjectはいじりたくないけどこのObjectを使ってちょっとした実験をしたいときですね。

活用できるシーンは少ないですが、機能として覚えておくといざというときの選択肢足り得る機能です。是非書いてみましょう。

 

監修してくれたメンター

大塚 颯斗

Ruby on Rails, PHP, Go を中心としたウェブアプリケーションエンジニアとして都内のウェブサービスを提供する企業に在籍。
最近はPHPを主に書きながら、オブジェクト指向をうまく適用していくことに関心を寄せています。

家で飼っている猫が好きだが、何故かすぐに猫に攻撃されて嫌われているかもしれない、というのが悩み。

 

大石ゆかり

内容分かりやすくて良かったです!

田島悠介

ゆかりちゃんも分からないことがあったら質問してね!

大石ゆかり

分かりました。ありがとうございます!

TechAcademyでは初心者でも最短4週間でエンジニアになれるRuby on Railsオンラインブートキャンプを開催しています。

現役エンジニアがパーソナルメンターとして受講生に1人ずつつき、マンツーマンのメンタリングで学習をサポートし、最短4週間でオリジナルWebサービスを開発することが可能です。

また、現役エンジニアから学べる無料のプログラミング体験会も実施しているので、ぜひ参加してみてください。