|
|
Log In | Not a Member? |
Contact ADC |
| < 前ページ次ページ > |
このセクションでは、メッセージ送信の構文について説明します。メッセージ式をネストする方法なども取り上げます。また、オブジェクトのインスタンス変数の「可視性」や、ポリモーフィズムと動的バインディングの概念も説明します。
メッセージの構文
nilへのメッセージ送信
レシーバのインスタンス変数
ポリモーフィズム(多態性)
動的バインディング
オブジェクトに何かを実行させるには、メソッドの適用を指示するメッセージをオブジェクトに送信します。Objective-C では、メッセージ式を大括弧で囲みます。
[receiver message] |
receiverはレシーバとなるオブジェクトであり、messageは実行すべきことをオブジェクトに通知します。ソースコードでは、メッセージは単にメソッドの名前とそれに渡される引数です。メッセージを送信すると、ランタイムシステムは、レシーバの持つすべてのメソッドの中から適切なメソッドを選択して呼び出します。
たとえば、次のメッセージは、myRectオブジェクトに対して、長方形を表示するdisplayメソッドを実行するように指示します。
[myRect display]; |
メソッドは、引数をとることもあります。次のメッセージ例は、myRectに対して、ウインドウ内の位置を座標(30.0, 50.0)に設定するように指示しています。
[myRect setOrigin:30.0 :50.0]; |
ここで、メソッド名setOrigin::には、各引数に1つずつ、計2つのコロンが含まれています。引数は、コロンの後に挿入します。このメソッド名は、ラベルのない引数を使用しています。ラベルのない引数を使用すると、メソッドの引数の種類と目的を特定しにくくなります。代わりに、各引数を説明するラベルをメソッド名に含める必要があります。引数ラベルは、メソッド名の各コロンの前に置きます。たとえば、次のsetWidth:height:メソッドでは、2つの引数の目的が明確です。
[myRect setWidth:10.0 height:15.0]; |
非常にまれですが、メソッドには、可変引数をとるものもあります。付加的な引数は、メソッド名の後に、コンマで区切って指定します(コロンと異なり、コンマは名前の一部と見なされません)。次の例では、makeGroup:メソッドに、1つの必須引数(group)と3つのオプション引数を渡しています。
[receiver makeGroup:group, memberOne, memberTwo, memberThree]; |
標準のC関数と同じように、メソッドは値を返すことができます。次の例では、myRectを塗りつぶした長方形として描画する場合はisFilled変数をYESに、輪郭だけ描画する場合はNOに設定します。
BOOL isFilled; |
isFilled = [myRect isFilled]; |
変数とメソッドは、同じ名前を持てることに注意してください。
メッセージ式は、別のメッセージ式内にネストすることができます。次の例では、ある長方形の色を別の長方形の色に設定します。
[myRect setPrimaryColor:[otherRect primaryColor]]; |
Objective-Cでは、nilへのメッセージ送信が可能です(実行時に影響はありません)。Cocoaでは、これを利用するにはいくつかのパターンがあります。メッセージからnilに返される値も有効です。
メソッドがオブジェクト、任意のポインタ型、sizeof(void*)以下のサイズの任意の整数スカラー値、float、double、long double、またはlong longを返す場合、nilに送信されたメッセージは0を返します。
メソッドがstructを返す場合、『Mac OS X ABI Function Call Guide』で定義されているようにレジスタに返されることになっているため、データ構造体のどのフィールドにもnilに送信されたメッセージは0.0を返します。その他のstructデータ型では0のみになることはありません。
メソッドが前述の値の型以外のものを返す場合、nilに送信されたメッセージの戻り値は不定です。
次のコードの一部はnilへのメッセージ送信の正しい使い方を示しています。
id anObjectMaybeNil = nil; |
// これは有効 |
if ([anObjectMaybeNil methodThatReturnsADouble] == 0.0) |
{ |
// 実装が続く… |
} |
メソッドは、受信側オブジェクトのインスタンス変数に自動的にアクセスできます。インスタンス変数を引数としてメソッドに渡す必要はありません。たとえば、上記のprimaryColorメソッドは引数を持ちませんが、otherRectのプライマリカラーを検出して返すことができます。すべてのメソッドはレシーバとそのインスタンス変数を引き継ぐため、それらを引数として宣言する必要はありません。
このような規則により、Objective-Cのソースコードは簡素化されます。また、オブジェクトとメッセージに対するオブジェクト指向プログラマの考え方もサポートされています。手紙が家庭に配達されるように、メッセージはレシーバに送信されます。メッセージ引数は、外部の情報をレシーバにもたらします。レシーバを取得してくる必要はありません。
メソッドは、レシーバのインスタンス変数にのみ自動的にアクセスできます。メソッドが別のオブジェクトに格納されている変数に関する情報を必要とする場合は、その変数の内容を明らかにするように要求するメッセージを該当するオブジェクトに送信する必要があります。上記のprimaryColorおよびisFilledメソッドは、まさにこの目的で使用しています。
インスタンス変数への参照の詳細については、クラスの定義を参照してください。
上記の例に示したように、Objective-Cのメッセージは、標準のC関数呼び出しと同じ構文上の位置に指定されます。しかし、メソッドはオブジェクトに属するため、メッセージは関数呼び出しとは異なる振る舞いをします。
特に、オブジェクトは、オブジェクト用に定義されたメソッドによってのみ操作できます。他のオブジェクトが同じ名前のメソッドを持っていても、他のオブジェクト用に定義されたメソッドと混同されることはありません。つまり、2つのオブジェクトは、同じメッセージに対して異なる応答をすることができます。たとえば、displayメッセージを送信された各オブジェクトは、それぞれ独自の方法で自身を表示することができます。CircleとRectangleは、カーソルを追跡する同じ指示に対して異なる応答をします。
この機能はポリモーフィズムと呼ばれ、オブジェクト指向プログラムの設計において重要な役割を果たします。動的バインディングとポリモーフィズムにより、さまざまな種類の多数のオブジェクトに適用できるコードを作成でき、コードを書く時点ではオブジェクトの種類を選択する必要はありません。たとえば、他のプロジェクトに取り組んでいる別のプログラマが後で開発するオブジェクトであってもかまいません。id変数にdisplayメッセージを送信するコードを書く場合は、displayメソッドを持つオブジェクトすべてが潜在的なレシーバになります。
関数呼び出しとメッセージの大きな違いは、関数とその引数がコンパイル時にコードの中で結合されるのに対して、メッセージと受信側のオブジェクトはプログラムを実行してメッセージが送信されるまで結合されないことです。したがって、メッセージに応答するために呼び出される実際のメソッドは、コードのコンパイル時ではなく、実行時にのみ知ることができます。
メッセージが実際に呼び出すメソッドは、レシーバによって決まります。さまざまなレシーバが、同じメソッド名の異なるメソッド実装を持つことができます(ポリモーフィズム)。コンパイラが、メッセージに対する正しいメソッド実装を見つけるには、レシーバがどのようなオブジェクトなのか(どのクラスに属するか)を知る必要があります。この情報は、レシーバが実行時にメッセージを受信するとき提示できますが(動的型定義)、ソースコード内の型宣言からは分かりません。
メソッド実装の選択は、実行時に行われます。メッセージが送信されると、ランタイムメッセージングルーチンが、レシーバとメッセージに指定されたメソッド名を確認します。このルーチンは、メソッド名の一致するレシーバのメソッド実装を検出して、そのメソッドを呼び出し、レシーバのインスタンス変数へのポインタを渡します(このルーチンの詳細については、メッセージングの仕組みを参照してください)。
このように、メッセージのメソッド名はメソッド実装を選択する役割を担います。このような理由から、メッセージのメソッド名は、セレクタとも呼ばれます。
このような、メッセージに対するメソッドの動的バインディングは、ポリモーフィズムと連携することにより、オブジェクト指向プログラミングに対してより高い柔軟性と能力を提供します。各オブジェクトが独自のメソッドを持つことができるため、メッセージ自身を変えるのではなく、メッセージを受信するオブジェクトを変えることで、プログラムはさまざまな結果を得ることができます。これは、プログラム実行時に行えるため、レシーバを「その場」で決めることができ、ユーザ操作などの外部要因に応じて決まるようにもできます。
たとえば、Application Kitをベースにしたコードを実行している場合は、どのオブジェクトが「カット」、「コピー」、および「ペースト」などのメニューコマンドからメッセージを受信するかはユーザが決めます。メッセージは、現在の選択を制御している任意のオブジェクトに送信されます。テキストを表示するオブジェクトは、copyメッセージに対して、スキャン画像を表示するオブジェクトとは異なる反応を示します。一連の形状を表すオブジェクトは、Rectangleとは異なる応答をします。メッセージが実行時までメソッドを選択しない(メソッドがメッセージにバインドされない)ため、応答の違いはメッセージに応答するメソッド内に隔離されます。メッセージを送信するコードは、それらの違いを考慮する必要はありませんし、可能性を列挙する必要もありません。アプリケーションはそれぞれに、copyメッセージに独自の方法で応答する、独自のオブジェクトを作成することができます。
Objective-Cでは動的バインディングをさらに一歩進めて、送信するメッセージ(メソッドセレクタ)も、実行時に決定する変数にすることができます(詳細については、メッセージングの仕組みを参照してください)。
| < 前ページ次ページ > |
Last updated: 2007-10-31
|
Get information on Apple products.
Visit the Apple Store online or at retail locations. 1-800-MY-APPLE Copyright © 2007 Apple Inc. All rights reserved. | Terms of use | Privacy Notice |