【コラム】
前回は、Prototypeパターンの基本的な実装を紹介した。その結果、ある意味当然だが、Prototypeパターンではオブジェクトのコピーが重要な事が分かったと思う。
そこで、今回はObjective-CとCocoaにおける、コピー機能の紹介をしよう。非常に基本的な機能なのだが、議論すべき点はたくさんある。
まず、最も単純なコピーから考えてみよう。コピーする対象はオブジェクトなのだが、いくらオブジェクトといっても所詮はメモリ上のデータなので、同じサイズのメモリ領域を確保して値をコピーしてやれば、コピーは完了する。Objective-CはC言語とのハイブリッドなので、mallocとmemcpyを使えばいい。
といっても、それでは原始的すぎるので、Cocoaではオブジェクトの単純なコピーをサポートする関数が用意されている。NSCopyObjectだ。定義は次のようになる。
NSCopyObjectは、3つの引数を取る。最初の引数は、コピーの対象となるオブジェクト。2つ目は、コピーしたオブジェクトに、余分なメモリ領域を加えるかどうか指示する。たとえば、インスタンス変数の領域を増やしたいときなどに使えるだろう。3つ目の引数は、コピーを行うゾーンを指定する。ゾーンについては次回説明しよう。
この関数を使うと、オブジェクトのコピーは次のようになる。
これで、もとのオブジェクトとまったく同じオブジェクトができ上がる。
通常のメモリ領域のコピーならばこれで終わりだが、オブジェクトの場合は、これだけでは十分ではない。問題となるのは、インスタンス変数として、他のオブジェクトへの参照があるときだ。この場合、参照の値だけをコピーするのか、それとも参照しているオブジェクトもコピーするのかを、決めなくてはならない。
このとき、前者を浅いコピー(shallow copy)、後者を深いコピー(deep copy)と呼ぶ。NSCopyObjectによって行われるのは、浅いコピーだ。
|
また、Objective-Cならではの問題として、浅いコピーを行ったときに、オブジェクトに新たにretainを投げて参照カウントを増やすのかどうか、という問題もある。
どのスタイルのコピーを採用するのかは、オブジェクトごとに個別に対応する必要がある。そこで、コピーメソッドの実装のために提供されるのが、前回も紹介した、copyWithZone:メソッドなわけだ。このメソッドの中で、浅いコピー、深いコピー、retainを伴う浅いコピー、を必要に応じて実装する。
ちなみに、NSObjectにはcopyというメソッドが用意されているが、これはcopyWithZone:を呼び出すものなので、これを実装しているオブジェクトでしか呼び出す事ができない。それに対してNSCopyObjectは、単純にメモリをコピーするだけなので、すべてのオブジェクトに対して呼び出す事が可能だ。ただし、NSCopyObjectでは浅いコピーしかできないので、そのオブジェクトが意図するコピーを行うためにも、特別な場合を除いてcopyメソッドを使うべきだろう。
例を示そう。_titleというインスタンス変数を持つオブジェクトに、コピーメソッドを実装してみる。_title変数も、一緒にコピーしよう。
まず、allocとinitを使いコピーするオブジェクトを作る。そこに、copyWithZone:でコピーした_titleを設定している。これを、retainした_titleを渡すようにしてやれば、retainを伴った浅いコピーとなる。
インスタンス変数をコピーするには、copyWithZone:を使う方法と、alloc+initを使う方法とがあるだろう。これも、状況に応じて使い分ける事になる。
深いコピーは、インスタンス変数の構造が複雑になると大変だが、Cocoaによるサポートもある。たとえば、配列を表すNSArrayクラスには、保持しているオブジェクトを深いコピーするかどうかを指定できる初期化メソッドがある。先ほどのList 3.に、_namesというNSArray型の変数を付け加えて、深いコピーをしてみよう。
initWithArray:copyItmes:というメソッドを使ってコピーしている。2つ目の引数にYESを指定すれば、配列の中身をすべてコピーしてくれる便利なメソッドだ。NOを指定した場合は、retainを投げる事になる。
このように、一口に「コピー」といっても、気をつけなくてはいけない事はたくさんある。始めのうちは、浅いコピーと深いコピーは混同しやすいので、十分気を付けてほしい。
次回も、コピーにまつわる話を続けよう。
| 深海底の熱水ヒントに“ナノ・エマルション”生成 [17:35 5/20] |
| JAEA、世界最高クラスのスピン偏極率をもった陽電子ビームの開発に成功 [16:11 5/20] |
| 【レポート】千葉高校生が快挙! 日本人初の部門最優秀賞受賞! - ISEF 2013 [11:59 5/20] |
| アシアル、モバイルアプリデベロッパー動向レポートの日本語版を公開 [11:36 5/20] |
| 【レポート】いよいよ審査! 密閉空間で1000人の審査員を迎えた代表8人--Intel ISEF 2013 [10:41 5/20] |
|
[大泉洋]エッセーが発売1カ月で15万部突破 本人も驚きのヒット [00:00 5/21] ホビー |
|
【特別企画】Samsung SSD 840でPCゲームが快適に - ヘビーゲームの読み込みが3倍に高速化 [00:00 5/21] パソコン |
|
【レビュー】高速・多機能で期待のIEEE802.11ac対応Wi-Fiルータ - NECアクセステクニカ「AtermWG1800HP」「AtermWG1400HP」 [00:00 5/21] パソコン |
|
リアーナが約8億の損害賠償を求めてトップショップ提訴、Tシャツを無断販売 [23:30 5/20] エンタメ |
|
「鬼灯の冷徹」カプセルトイ、キャラがこけし型の根付に [23:19 5/20] ホビー |