|
|
Log In | Not a Member? |
Contact ADC |
| < Previous PageNext Page > |
Objective-Cの言語とランタイムだけでは、最も単純なオブジェクト指向プログラムさえ構築するには十分ではありません。少なくとも、簡単ではありません。すべてのオブジェクトに共通する基本的な動作とインターフェイスの定義という、重要な要素が欠けています。それらの定義を提供するのがルートクラスです。
ルートクラスは、クラス階層(この場合はCocoaのクラス階層)のルートに位置することからその名が与えられています。ルートクラスはほかのどのクラスも継承せず、階層内のほかのすべてのクラスは最終的にルートクラスを継承します。Objective-Cの言語とともに、ルートクラスはCocoaがObjective-Cのランタイムに直接アクセスしてやり取りする際の中心的な場所になります。Cocoaオブジェクトのオブジェクトとしての動作機能は、主にルートクラスに由来します。
CocoaではNSObjectとNSProxyの2種類のルートクラスが用意されています。Cocoaでは、抽象スーパークラスである後者のクラスを、ほかのオブジェクトの代役として機能するオブジェクトとして定義しています。そのため、NSProxyは分散オブジェクトアーキテクチャにおいて必要不可欠です。このような特別な役割のため、NSProxyはCocoaプログラムではあまり登場しません。Cocoaの開発者がルートクラスや基本クラスを引き合いに出すときは、ほとんど常にNSObjectのことを指しています。
このセクションでは、NSObjectについて説明し、NSObjectとランタイムとのやり取り、およびすべてのCocoaオブジェクトに対してNSObjectで定義されている基本的な動作とインターフェイスについて、解説します。特に、割り当て、初期化、メモリ管理、イントロスペクション、およびランタイムサポートを行うために宣言されている各メソッドについて説明します。これらの概念はCocoaを理解するための基礎になります。
NSObject
ルートクラス、およびプロトコル
ルートクラスのメソッドの概要
インターフェイスに関する規則
インスタンスメソッドとクラスメソッド
NSObjectはほとんどのObjective-Cクラス階層のルートクラスであり、スーパークラスを持ちません。ほかのクラスは、 Objective-C言語のランタイムシステムへの基本的なインターフェイスをNSObjectから継承し、そのインスタンスは、オブジェクトとして動作する機能を得ます。
NSObjectは厳密には抽象クラスではありませんが、事実上抽象クラスであると言えます。NSObjectのインスタンスは単独では、単純なオブジェクトとして存在する以外に、役に立つことはできません。プログラムに対して固有の属性やロジックを追加するには、NSObjectクラスを継承するクラス、またはNSObjectから派生したほかのクラスを継承するクラスを、1つ以上作成する必要があります。
NSObjectでは NSObjectプロトコルを採用しています(“「ルートクラス、およびプロトコル」”を参照)。NSObjectプロトコルでは、複数のルートオブジェクトの使用が可能です。たとえば、もう一方のルートクラスであるNSProxyは、NSObjectを継承しませんが、NSObjectプロトコルを採用しているため、ほかのObjective-Cオブジェクトと共通のインターフェイスを共有します。
NSObjectは java.lang.Objectとともに、FoundationとApplication Kitを含め、JavaにおけるすべてのCocoa要素のルートクラスになります。
NSObjectはクラスの名前だけではなくプロトコルの名前も表します。どちらも、Cocoaにおけるオブジェクトの定義に必要不可欠です。NSObjectプロトコルでは、Cocoa内のすべてのルートクラスに必要とされる基本的なプログラムインターフェイスを規定しています。そのため、NSObjectプロトコルはまったく同じ名前のクラスで採用されているだけでなく、もう一方のCocoaルートクラスであるNSProxyでも採用されています。NSObjectクラスではさらに、プロキシオブジェクトではないすべてのCocoaオブジェクトに対する基本的なプログラムインターフェイスも規定しています。
NSObjectなどのプロトコルは、複数のルートクラスを可能にするために、それらのプロトコルメソッドをクラスインターフェイスに含めるのではなく、Cocoaオブジェクトの定義全体で使用されます。ルートクラスはそれぞれ、採用しているプロトコルによって定義されている共通のインターフェイスを共有します。
別の言い方をすれば、NSObjectだけが唯一の“ルート”プロトコルではありません。NSObjectクラスでは、NSCopying、NSMutableCopying、NSCodingの各プロトコルが正式には採用されていませんが、これらのプロトコルに関連するメソッドが宣言され実装されています(さらに、NSObjectクラスの定義が含まれているNSObject.hヘッダファイルには、前述の4つのプロトコルすべての定義が含まれています)。オブジェクトのコピー、エンコード、およびデコードは、オブジェクトの動作の基本的な一面です。ほとんどすべてというわけではありませんが、サブクラスの多くは、これらのプロトコルの採用またはプロトコルへの準拠が想定されています。
注: ほかのCocoaクラスは、カテゴリを通じてメソッドをNSObjectに追加することができ、また実際に追加しています。これらのカテゴリはしばしば委任で使用される簡易プロトコルであり、カテゴリのどのメソッドを実装するかをデリゲートが選べるようにしています。ただし、NSObjectのこれらのカテゴリは、基本オブジェクトインターフェイスの一部とは見なされません。
NSObjectルートクラスは、採用されているNSObjectプロトコルやほかの“ルート”プロトコルとともに、プロキシ以外のすべてのCocoaオブジェクトに対して、次のインターフェイス特性と動作特性を規定します。
割り当て、初期化、および複製。NSObjectのメソッドの一部(採用されているプロトコルからのものも含む)は、オブジェクトの作成、初期化、および複製を処理します。
allocおよびallocWithZone:メソッドは、オブジェクトのメモリをメモリゾーンから割り当て、その実行時のクラス定義を指し示すようにオブジェクトを設定します。
initメソッドは、オブジェクトの初期化のためのプロトタイプで、オブジェクトのインスタンス変数を既知の初期状態に設定するプロシージャです。クラスメソッドinitializeおよびloadは、初期化をクラス自身が行う機会を与えます。
copyおよびcopyWithZone:メソッドは、これらのメソッド(NSCopyingプロトコルからのもの)を実装しているクラスのメンバとなっている任意のオブジェクトのコピーを作成します。 mutableCopyおよびmutableCopyWithZone:(NSMutableCopyingプロトコルで定義されています)は、オブジェクトの可変コピーを作成する必要があるクラスによって実装されます。
詳細については、“「オブジェクトの作成」”を参照してください。
オブジェクトの保持と破棄。次の各メソッドは、オブジェクト指向プログラムのメモリ管理にとって特に重要です。
詳細については、“「Cocoaオブジェクトのライフサイクル」”を参照してください。
イントロスペクションと比較。NSObjectのメソッドの多くでは、オブジェクトに関する実行時の問い合わせが可能です。これらのイントロスペクションメソッドは、クラス階層におけるオブジェクトの位置を調べたり、オブジェクトに特定のメソッドが実装されているかどうかを調べたり、オブジェクトが特定のプロトコルに準拠しているかどうかをテストしたりするのに役立ちます。イントロスペクションメソッドにはクラスメソッドのみのものがあります。
superclassおよびclassメソッド(クラスおよびインスタンス)は、それぞれレシーバのスーパークラスおよびクラスをClassオブジェクトとして返します。
isKindOfClass:およびisMemberOfClass:メソッドを使用して、オブジェクトが属するクラスを知ることができます。後者のメソッドは、レシーバが指定のクラスのインスタンスかどうかをテストするために使用します。クラスメソッドisSubclassOfClass:は、クラスの継承をテストします。
respondsToSelector:メソッドは、セレクタによって識別されるメソッドをレシーバで実装しているかどうかをテストします。クラスメソッドinstancesRespondToSelector:は、指定のクラスのインスタンスに、指定のメソッドが実装されているかどうかをテストします。
conformsToProtocol:メソッドは、レシーバ(オブジェクトまたはクラス)が指定のプロトコルに準拠しているかどうかをテストします。
descriptionメソッドを使用すると、オブジェクトの内容を記述した文字列をオブジェクトから返すことができます。しばしば、この出力はデバッグ(“print object”コマンド)に使用されます。また、書式付き文字列の中でオブジェクトの“%@”指定子によって使用されます。
詳細については、“「イントロスペクション」”を参照してください。
オブジェクトのエンコードとデコード。次のメソッドは(アーカイブ処理の一部として)オブジェクトのエンコードとデコードに関係します。
encodeWithCoder:およびinitWithCoder:メソッドはNSCodingプロトコルのメンバです(NSCodingプロトコルにはこれらのメンバしかありません)。前者は、オブジェクトのインスタンス変数をエンコードできるようにします。後者は、デコードされたインスタンス変数からオブジェクト自身を初期化できるようにします。
NSObjectクラスではオブジェクトのエンコードに関係するほかのメソッドも宣言しています。それらは、classForCoder:、replacementObjectForCoder:、およびawakeAfterUsingCoder:です。
詳細については、『Archives and Serializations Programming Guide for Cocoa』を参照してください。
メッセージの転送。forwardInvocation:とその関連メソッドは、あるオブジェクトから別のオブジェクトへのメッセージの転送を可能にします。
メッセージのディスパッチ。performSelector...で始まる一連のメソッドを使用すると、指定した遅延の後にメッセージをディスパッチしたり、二次スレッドからメインスレッドにメッセージを(同期的に、または非同期で)ディスパッチしたりできます。
このほか、NSObjectのメソッドにはバージョン管理やなりすましのためのクラスメソッドなどがあります(なりすましを使用すると、クラスがランタイムに対して別のクラスとして見えるようにすることができます)。また、メソッドセレクタや、メソッド実装への関数ポインタなど、実行時のデータ構造にアクセスできるメソッドもあります。
NSObjectメソッドには、呼び出されることのみを目的とするものや、オーバーライドを意図したものがあります。たとえば、ほとんどのサブクラスではallocWithZone:をオーバーライドせずに、initを実装することが求められます。あるいは少なくとも、最終的にルートクラスのinitメソッドを呼び出すイニシャライザを実装することが求められます(“「オブジェクトの作成」”を参照)。サブクラスによるオーバーライドを前提としたメソッドのうち、NSObjectに実装されているものは、何も実行しないか、selfなどの妥当なデフォルト値を返すかのどちらかです。このようなデフォルト実装のおかげで、クラスにおいてメソッドをオーバーライドしていないオブジェクトを含め、任意のCocoaオブジェクトに対して、initなどの基本的なメッセージを、実行時例外発生の危険を冒すことなく送信することが可能になります。メッセージを送信する前に(respondsToSelector:を使用して)チェックする必要はありません。さらに重要なこととして、NSObjectの“プレースホルダ”メソッドによって、Cocoaオブジェクトの共通の構造が定義され、オブジェクトのやり取りの信頼性が向上する規則が確立されます(すべてのクラスがその規則に従う場合)。
ランタイムシステムでは、ルートクラスで定義されているメソッドが特別な方法で扱われます。ルートクラスで定義されているインスタンスメソッドは、インスタンスとクラスオブジェクトの両方で実行できます。したがって、すべてのクラスオブジェクトが、ルートクラスに定義されているインスタンスメソッドにアクセスできます。同じ名前のクラスメソッドを持っていない限り、どのクラスオブジェクトも、ルートの任意のインスタンスメソッドを実行できます。
たとえば、クラスオブジェクトにメッセージを送信して、NSObjectのrespondsToSelector:とインスタンスメソッドperformSelector:withObject:を実行できます。
SEL method = @selector(riskAll:); |
if ([MyClass respondsToSelector:method]) |
[MyClass performSelector:method withObject:self]; |
クラスオブジェクトで使用できるインスタンスメソッドは、そのルートクラスで定義されているものだけです。上記の例では、仮にMyClassにおいてrespondsToSelector:かperformSelector:withObject:のどちらかを再実装したとすれば、それらの新しいバージョンはインスタンスにおいてのみ使用できます。MyClassのクラスオブジェクトでは、NSObjectクラスに定義されているバージョンだけを実行できます(もちろん、MyClassにおいてrespondsToSelector:またはperformSelector:withObject:をインスタンスメソッドとしてではなくクラスメソッドとして実装した場合には、それらの新しいバージョンがクラスで実行されることになります)。
| < Previous PageNext Page > |
Last updated: 2006-05-23
|
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 |