【コラム】
ダイナミックObjective-C
10 非形式プロトコル - もう1つのプロトコル
2005/10/12
前回は、Objective-Cのプロトコルについて説明したが、その利点としてプロセス間通信の抑制という点を挙げた。だが、プロトコルは、もう一つの側面である「オブジェクトの振る舞いを表すメソッドの集合」をするもの、という文脈で語られることが多い。この説明を後回しにしたのは、この機能は「もう1つのプロトコル」で実現されることが多いからだ。今回は、このことを説明しよう。
非形式プロトコル
前回説明したように、プロトコルは「@protocol」という、特別な文法を導入している。だが、メソッドの集合を宣言するだけなれば、わざわざ新しい文法を使う必要はない。カテゴリを使えばよい。ただし、ちょっとコツがいる。Objective-Cのルートクラスである、NSObjectのカテゴリとして宣言するのだ。
実際の例を紹介しよう。Cocoaでは、テーブルビューを表示するために、NSTableViewというクラスがある。NSTableViewでは、テーブルに表示するデータを、データソースとなるオブジェクトから取得する。データソースのために必要なメソッドは、NSTableDataSourceプロトコルで定義されている。次の宣言だ。
- (int)numberOfRowsInTableView:(NSTableView*)tableView;
- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)tableColumn row:(int)row;
@end
これは、テーブルのデータソースのためのメソッドの集合なので、機能の意味としてはプロトコルだ。だが、@protocol指示子は使わずに、NSObjectのカテゴリとして宣言されている。これを非形式プロトコルと呼ぶ。@protocolによるものは、特に区別するために形式プロトコルと呼ぶこともある。
非形式プロトコルの使い方
では、非形式プロトコルを、あるクラスに準拠させるときのことを考えてみよう。とはいっても、実は何も特別なことはないのだが。
まず、非形式プロトコルを実装するとき、特別な宣言は何もいらない。なぜならば、ルートクラスであるNSObjectで、すでに宣言されているのだから。いきなり、必要なメソッドを実装してしまえばいい。
ということは、あるクラスが非形式プロトコルに準拠しているかどうか確かめる手段は、メソッドの実装を調べるためのrespondsToSelector:を使うしかないのである。形式プロトコルの場合は、conformsToProtocol:というメソッドで調査できた。非形式プロトコルの場合には、これに対応するものはない。
だから、コンパイラによる実装漏れのチェックなどは、もちろんない。たとえば、あるクラスでNSTableDataSourceプロトコルを実装する、と決めても、そのための宣言はなにもないのだから、実際にそのメソッドを実装したかどうかは、プログラマが責任を持つことになる。あとは、実行時にrespondsToSelector:を使って調べるだけである。
つまり、ただ単なるメソッドの集合であり、言語によるサポートはまったくといっていいほどない。
非形式プロトコルの利点
言語仕様という点から見ると、まったくつまらない非形式プロトコルだが、もちろん存在理由がある。いや、実際のところ、Cocoaで提供されているプロトコルを調べると、形式プロトコルよりも非形式プロトコルの方が圧倒的に多いのである。文法的にはなんのサポートもない、非形式プロコトルが好まれる理由は何であろうか?
非形式プロトコルが適しているものとして、宣言されているメソッドの実装が任意である場合、が挙げられる。つまり、すべてのメソッドを実装する必要がない場合だ。具体的な例としては、デリゲートがある。
デリゲートは、日本語では委譲と訳される、あるクラスの動作の「判断」を、外部のオブジェクトにゆだねるための機構だ。たとえば、Cocoaではウィンドウを表すNSWindowというクラスがある。このクラスは基本的な動作、たとえばウィンドウの移動や、ウィンドウのリサイズ、を行う前に、デリゲートに実行してもいいかどうか問い合わせてくる。デリゲートは、アプリケーションの状況に応じて、実行を許可したり、リサイズの大きさを特別な値に変更したりする。
このような、デリゲートで使われるメソッドは、非形式プロトコルで宣言されている。デリゲートのメソッドは、結構な数になることが多い。だがその中の、1つか2つのメソッドしか使わないこともよくある。このような場合、形式プロトコルを使うと、宣言されているすべてのメソッドを実装することが求められるので、中身が空のメソッドが多数できてしまう。非形式プロトコルの方が適切だ。
次回はこの、非形式プロトコルによるデリゲートについて、掘り下げてみよう。
ヘッドライン
- 【連載】『TechNet』の歩き方 第21回 リニューアルしたTechNet Online[09:00 3/18]WinServer2008 R2 導入体験記
- 【ハウツー】概説 Springプロダクト(2) - 柔軟な配備を可能にするSpring DM[09:00 3/18]プログラミング
- CAD利用技術者試験 前期試験の申込み受付開始[09:00 3/18]SE力
- 富士通、集中冷却方式を採用した高密度サーバ製品を販売開始[09:00 3/18]サーバとストレージ
- RSA、情報漏洩対策ソリューション「RSA Data Loss Prevention」を発表[08:00 3/18]セキュリティ
- 【連載】佐々木正悟×堀E正岳 ライフハック・トーク 第32回 Evernoteでデジタルに記憶する[07:30 3/18]SE力
- 京大ら、宇宙天気予報の基礎となる太陽嵐のモデリングに成功[20:09 3/17]サイエンス
- IBMら、環境的に持続可能な新しいプラスチックに向けた研究成果を発表[19:40 3/17]サイエンス
- 東北大、従来比で桁違いに特性の優れたCNT-TFTの作製方法を開発[19:09 3/17]エレクトロニクス
- CSR、Androidスマートフォン開発用ソフトプラットフォームを発表[18:06 3/17]エレクトロニクス





