2019/3/14 Marp Web (under construction)
http://localhost:8080/ 1/14
コピーの話
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 2/14
コピーには2種類がある
シャローコピー(ShallowCopy)
ディープコピー(DeepCopy)
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 3/14
シャローコピー
コピー元とコピー先がメモリ上の同じデータ(インスタンス変数)を参照している
中身は同じ
名前が違うだけ
AさんのシャローコピーであるBさんを殴ると、Bさんだけでなくコピー元のAさん
もダメージを受けるような感じ
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 4/14
ディープコピー
オブジェクトのみのコピーではなく、オブジェクトとメモリ上のデータ(インスタ
ンス変数)の両方をコピーする
完全に別物のクローンを作るイメージ
AさんのディープコピーであるBさんを殴ると、ダメージを受けるのはBさんだけ
というイメージ
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 5/14
C/C++だと
ポインタみたいなもん
というかポインタ
多分ポインタ
参照渡しとか値渡しとかそのへんの話
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 6/14
rubyで分かりやすく
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 7/14
= による複製
=によってオブジェクトを複製すると、両者は名前が違うだけの同じ中身を参照す
ることになる
なので、破壊的変更を加えると複製元も先も変わる
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 8/14
例として
hoge = [5 ,4 ,3 ,2 ,1]
foo = hoge
foo.sort!
foo
# => [1, 2, 3, 4, 5]
hoge
# => [1, 2, 3, 4, 5]
fooをsort!したのにhogeも変わってしまった!
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 9/14
dup/cloneによる複製
dupとcloneの違いはここでは取り上げない
hoge = [5, 4, 3, 2 ,1]
foo = hoge.dup
foo.sort!
foo
# => [1, 2, 3, 4, 5]
hoge
# => [5, 4, 3, 2, 1]
お、いけてる!
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 10/14
と思いきや
hoge = [5, 4, 3, 2, 1]
foo = [hoge]
# => [[5, 4, 3, 2, 1]]
bar = foo.dup
bar[0].sort!
bar
# => [[1, 2, 3, 4, 5]]
foo
# => [[1, 2, 3, 4, 5]]
あ、あれ~~~。。。
なぜかfooも変わっちゃってんじゃん!
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 11/14
実はdup、cloneも浅いコピー(シャローコピー)
dup,cloneは、複製するオブジェクト自体は別物になる(ガワは別物)
しかしそれに含まれるオブジェクトの参照先はそのままコピー
なので最初に例に挙げた配列みたいなものだとintegerをそのままコピーするだけ
なので別物になる
2次元配列などになってくると、中にあるオブジェクトの参照先情報などもコピー
されてしまう
つまり、dupでコピーされるのは自分自身のオブジェクトだけ
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 12/14
結論
コピーには2種類ある
シャローコピー(ShallowCopy)
ディープコピー(DeepCopy)
オブジェクト意識せずに破壊的メソッド使うと痛い目を見る(かもね)
意識しておくと、いつかどこかで損しなくなるかも
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 13/14
余談
2019/3/14 Marp Web (under construction)
http://localhost:8080/ 14/14
じゃあディープコピーするにはどうしたらええねん
プレーンなruby
Rubyのデータ構造を文字列にエンコード・デコードするMarshalモジュールを使う
b = Marshal.load(Marshal.dump(a))
railsなら
ActiveSupportのdeep_dupを使う
b = a.deep_dup

コピーの話

  • 1.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 1/14 コピーの話
  • 2.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 2/14 コピーには2種類がある シャローコピー(ShallowCopy) ディープコピー(DeepCopy)
  • 3.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 3/14 シャローコピー コピー元とコピー先がメモリ上の同じデータ(インスタンス変数)を参照している 中身は同じ 名前が違うだけ AさんのシャローコピーであるBさんを殴ると、Bさんだけでなくコピー元のAさん もダメージを受けるような感じ
  • 4.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 4/14 ディープコピー オブジェクトのみのコピーではなく、オブジェクトとメモリ上のデータ(インスタ ンス変数)の両方をコピーする 完全に別物のクローンを作るイメージ AさんのディープコピーであるBさんを殴ると、ダメージを受けるのはBさんだけ というイメージ
  • 5.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 5/14 C/C++だと ポインタみたいなもん というかポインタ 多分ポインタ 参照渡しとか値渡しとかそのへんの話
  • 6.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 6/14 rubyで分かりやすく
  • 7.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 7/14 = による複製 =によってオブジェクトを複製すると、両者は名前が違うだけの同じ中身を参照す ることになる なので、破壊的変更を加えると複製元も先も変わる
  • 8.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 8/14 例として hoge = [5 ,4 ,3 ,2 ,1] foo = hoge foo.sort! foo # => [1, 2, 3, 4, 5] hoge # => [1, 2, 3, 4, 5] fooをsort!したのにhogeも変わってしまった!
  • 9.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 9/14 dup/cloneによる複製 dupとcloneの違いはここでは取り上げない hoge = [5, 4, 3, 2 ,1] foo = hoge.dup foo.sort! foo # => [1, 2, 3, 4, 5] hoge # => [5, 4, 3, 2, 1] お、いけてる!
  • 10.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 10/14 と思いきや hoge = [5, 4, 3, 2, 1] foo = [hoge] # => [[5, 4, 3, 2, 1]] bar = foo.dup bar[0].sort! bar # => [[1, 2, 3, 4, 5]] foo # => [[1, 2, 3, 4, 5]] あ、あれ~~~。。。 なぜかfooも変わっちゃってんじゃん!
  • 11.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 11/14 実はdup、cloneも浅いコピー(シャローコピー) dup,cloneは、複製するオブジェクト自体は別物になる(ガワは別物) しかしそれに含まれるオブジェクトの参照先はそのままコピー なので最初に例に挙げた配列みたいなものだとintegerをそのままコピーするだけ なので別物になる 2次元配列などになってくると、中にあるオブジェクトの参照先情報などもコピー されてしまう つまり、dupでコピーされるのは自分自身のオブジェクトだけ
  • 12.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 12/14 結論 コピーには2種類ある シャローコピー(ShallowCopy) ディープコピー(DeepCopy) オブジェクト意識せずに破壊的メソッド使うと痛い目を見る(かもね) 意識しておくと、いつかどこかで損しなくなるかも
  • 13.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 13/14 余談
  • 14.
    2019/3/14 Marp Web(under construction) http://localhost:8080/ 14/14 じゃあディープコピーするにはどうしたらええねん プレーンなruby Rubyのデータ構造を文字列にエンコード・デコードするMarshalモジュールを使う b = Marshal.load(Marshal.dump(a)) railsなら ActiveSupportのdeep_dupを使う b = a.deep_dup