Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page >

Cocoaクラスからの継承

Application Kitなどのフレームワークによって定義されるプログラムモデルは、汎用的なため、数多くの種類のアプリケーションで共通に利用できます。モデルが汎用的なので、当然ながらフレームワークのクラスによっては、抽象的であったり意図的に不完全であったりします。多くの場合、クラスでは作業の大部分を低レベルの共通のコードの中で実行しますが、動作の大きな部分を未完成のままにするか、安全ながらも汎用的な“デフォルト”の形に完成させます。

アプリケーションではしばしば、スーパークラスにおけるこれらの隙間を埋め、フレームワーククラスで欠けている部分を供給する、サブクラスを作成する必要があります。サブクラスは、アプリケーション固有の動作をフレームワークに追加するための主要な手段になります。カスタムのサブクラスのインスタンスは、フレームワークで定義されているオブジェクトのネットワークの中に位置を占め、ほかのオブジェクトと連携して動作する能力をフレームワークから継承します。たとえば、NSCellのサブクラスを作成すると、フレームワークに定義されているNSButtonCellNSTextFieldCell、その他のセルオブジェクトの場合と同様に、この新しいクラスのインスタンスをNSMatrixオブジェクトに表示できます。

サブクラスを作成する際の主な作業の1つは、スーパークラスで宣言されている(またはスーパークラスで採用されているプロトコルにある)特定のメソッド群を実装することです。継承したメソッドを実装しなおすことを、そのメソッドをオーバーライドすると言います。

In this section:

メソッドのオーバーライドを必要とする場合
サブクラスの作成を必要とする場合


メソッドのオーバーライドを必要とする場合

フレームワーククラスに定義されているメソッドのほとんどは十分な実装を持っています。これらは、メソッドをそのまま呼び出して、クラスが提供するサービスを利用できるようにするために存在します。このようなメソッドをオーバーライドする必要はほとんどなく、またオーバーライドするべきではありません。フレームワークは、それらのメソッドが実行する処理をそのまま利用します。それ以上のことも、それ以下のことも求めません。それ以外の場合は、メソッドをオーバーライドできますが、そうするべき本当の理由はありません。フレームワークが提供するメソッドは、十分な仕事をします。しかし、strcmpを使用せずに、独自の文字列比較関数を実装するのと同様に、必要であれば、フレームワークのメソッドをオーバーライドすることも選べます。

一方で、フレームワークメソッドによってはオーバーライドを前提とするものがあります。これらは、プログラム固有の動作をフレームワークに追加できるようにするために存在します。多くの場合、フレームワークによるそれらのメソッドの実装は、アプリケーションにとって意味のあることをほとんど、あるいはまったく何もしませんが、ほかのフレームワークメソッドから発信されるメッセージの中で呼び出されます。このようなメソッドに実質的な機能を与えるためには、アプリケーションで独自にメソッドを実装する必要があります。

呼び出しかオーバーライドか

サブクラスの中でオーバーライドするフレームワークのメソッドは、開発者が自分で呼び出すことは(少なくとも直接には)ありません。単純にメソッドを実装しなおして、残りの処理はすべてフレームワークに任せます。実のところ、アプリケーション固有のメソッドを記述する可能性が高いほど、それを自分のコードの中で呼び出す可能性は低くなります。これには確かな理由があります。一般に、フレームワーククラスでパブリックメソッドが宣言されているのは、開発者が次の2つのいずれかを実行できるようにするためです。

場合によっては両方に該当するメソッドもあります。呼び出せば有用なサービスを提供する一方で、必要があればオーバーライドすることもできるメソッドです。しかし、一般に、呼び出すことができるメソッドの場合、そのメソッドはフレームワークによって十分に定義されており、コードの中で定義しなおす必要はありません。サブクラスの中で実装しなおす必要があるメソッドの場合は、フレームワークにおいてそのメソッド固有の役割が決まっているので、メソッド自体が適宜呼び出されます。Figure 3-2は、この2種類のフレームワークメソッドを示します。


Figure 3-2  オーバーライドされたメソッドにメッセージを送るフレームワークメソッドの呼び出し

Figure 3-2 オーバーライドされたメソッドにメッセージを送るフレームワークメソッドの呼び出し

Cocoaフレームワークを使用したオブジェクト指向プログラミングの作業の大部分は、フレームワークによって組み立てられるメッセージを通じてプログラムが間接的にのみ使用するメソッドを実装する作業です。

オーバーライド対象メソッドの種類

サブクラスでは、複数の異なる種類のメソッドを定義できます。

メソッドのオーバーライドは必ずしも面倒な作業ではありません。多くの場合、コードに1、2行加えるだけという方法で、メソッドを慎重に実装しなおすことで、スーパークラスの動作に大幅な変更を加えることができます。また、独自版のメソッドを実装する際は、完全に自分だけの力で作業をこなさなければならないということはありません。Cocoaフレームワークによってすでに提供されているクラス、メソッド、関数、および型を利用できます。

サブクラスの作成を必要とする場合

クラスのどのメソッドをオーバーライドする必要があるかを知ることは重要ですが、それと同様に、その決定の前に、どのクラスを継承するのかを明らかにすることも重要です。継承元の決定は、明白な場合もあれば、簡単にはいかない場合もあります。ここでは、決定の際に参考となるデザイン上の考慮事項をいくつか示します。

まず、フレームワークを理解することです。個々のフレームワーククラスについて、その用途や機能に慣れるようにしてください。自分が必要としていることを行うクラスがすでに存在するかもしれません。また、自分が必要としていることをほぼ行うクラスを見つけることができれば幸運です。そのクラスは、カスタムクラスのスーパークラスの候補になります。サブクラス化は、自分のニーズに合わせて既存のクラスを再利用し、カスタマイズする作業です。継承したメソッドを1つだけオーバーライドし、元の動作とはわずかに異なる動作を実行するように手を加えるだけで、サブクラス化が済む場合もあります。あるいは、1つまたは2つの属性を(インスタンス変数として)スーパークラスに追加した後、それらの属性にアクセスして操作するメソッドを定義し、それらをスーパークラスの動作に組み込むことで、サブクラス化を行う場合もあります。

それ以外に、自分のサブクラスをクラス階層のどこに組み込むのが最適かを決めるうえで役立つ考慮事項があります。自分が作成しようとしているアプリケーション、またはアプリケーションの一部は、どのような特徴を持つものでしょうか。Cocoaのアーキテクチャの中には、独自のサブクラス化要件を要求するものもあります。たとえば、複数の文書を扱うアプリケーションの場合は、CocoaのドキュメントベースのアーキテクチャにおいてNSDocumentをサブクラス化する必要があり、おそらくほかのクラスもサブクラス化が必要になります。アプリケーションをスクリプト対応にする(つまり、AppleScriptのコマンドに対応できるようにする)には、NSScriptCommandなどのスクリプトクラスの1つをサブクラス化しなければならない可能性があります。

サブクラスのインスタンスがアプリケーションの中で果たす役割についても、考慮する必要があります。Cocoaの重要なデザインパターンであるModel-View-Controlデザインパターンでは、役割がオブジェクトに割り当てられます。これらは、ユーザインターフェイスに表示されるビューオブジェクトであったり、アプリケーションデータ(およびそれらのデータに作用するアルゴリズム)を保持するモデルオブジェクトであったり、ビューとモデルオブジェクトとの間を仲介するコントローラオブジェクトであったりします(詳細については、“「Model-View-Controllerデザインパターン」”を参照してください)。オブジェクトがどのような役割を果たすのかを知ることによって、どのスーパークラスを使用するかを決める際に、その選択肢を絞ることができます。クラスのインスタンスが、独自のカスタム描画とイベント処理を行うビューオブジェクトである場合は、おそらくNSViewからクラスを継承することになります。アプリケーションでコントローラオブジェクトが必要な場合は、既製のコントローラクラス(NSObjectControllerなど)の1つを使用するか、または別の動作を必要とする場合はNSControllerまたはNSObjectをサブクラス化します。作成するクラスが典型的なモデルクラスである場合(たとえば、各オブジェクトがスプレッドシート内の会社データの各行を表すようなクラスの場合)は、おそらくNSObjectをサブクラス化するか、Core Dataフレームワークを使用することになります。

さらに、サブクラス化が問題解決のための最適な手段でないこともあります。より適切な手段が存在するかもしれません。少数の簡易メソッドをクラスに追加するだけなら、サブクラスの代わりにカテゴリを作成することが考えられます。あるいは、Cocoa開発“ツールボックス”に含まれる、デザインパターンをベースとしたほかの数多くのリソースの1つを利用することもできます。このようなリソースには、委任、通知、ターゲット/アクションなどがあります(“「オブジェクトとの通信」”を参照)。スーパークラスの候補を決める際には、クラスのヘッダファイル(またはリファレンスドキュメント)をひととおり調べ、委任メソッドや通知など、サブクラス化をせずに必要な動作を実行できる何らかのメカニズムがないか確認します。

フレームワークのプロトコルについても同様に、そのヘッダファイルやドキュメントを調べることができます。プロトコルを採用することによって、複雑なサブクラスに伴う困難を避けながら目標を達成できる場合があります。たとえば、メニュー項目の有効状態を管理する必要がある場合は、カスタムコントローラクラスでNSMenuValidationプロトコルを採用することができます。この動作を実現するためにNSMenuItemNSMenuをサブクラス化する必要はありません。

オーバーライドを前提としていないフレームワークメソッドが存在するのと同様に、サブクラス化を前提としていないフレームワーククラスも存在します(NSFileManagerNSFontPanelNSLayoutManagerなど)。これらのクラスをあえてサブクラス化する場合は、十分な注意が必要です。フレームワーククラスによってはその実装が複雑なものがあり、ほかのクラスの実装と密接に統合されているものや、場合によってはオペレーティングシステムのさまざまな要素と密接に統合されているものがあります。多くの場合、フレームワークメソッドの動作を正確に複製したり、メソッドが持つと考えられる相互依存性や影響を推定することは、困難です。何らかのメソッド実装に加えた変更のために、予見不能な望ましくない影響が広範囲に生じる可能性もあります。

場合によっては、オブジェクト構成を使用してこのような困難を避けることもできます。オブジェクト構成とは、オブジェクトを“ホスト”オブジェクトに集め、ホストを通じてそれらのオブジェクトを管理し、カスタマイズした高度で複雑な動作を実現するという、汎用的な手法です(Figure 3-3を参照)。フレームワークの複雑なスーパークラスから直接継承するのではなく、そのスーパークラスのインスタンスをインスタンス変数として保持するカスタムクラスを作成します。カスタムクラスそのものは、ルートクラスであるNSObjectを直接継承するなど、かなり単純にできる可能性があります。継承という点では単純ですが、クラスでは埋め込まれたインスタンスを操作し、拡張し、強化します。クライアントオブジェクトから見れば、ある意味では、対象の複雑なスーパークラスのサブクラスと捉えることができますが、スーパークラスのインターフェイスを共有することはおそらくありません。オブジェクト構成の例として、Foundationフレームワーククラスの NSAttributedStringがあります。NSAttributedStringNSStringオブジェクトをインスタンス変数として保持しており、stringメソッドを通じてそれを公開しています。 NSStringは、文字列のエンコードや、文字列の検索、パス操作などの複雑な動作を実行するクラスです。NSAttributedStringはこれらの動作を強化し、フォントや色、位置揃え、段落スタイルなどの属性を一連の文字に付加する機能を追加します。そして、この機能追加を、NSStringをサブクラス化することなく実現します。


Figure 3-3  オブジェクト構成

Figure 3-3 オブジェクト構成

一見、スーパークラスの最適な候補と思われるものが、最適な選択でないこともあります。ご存知のように、NSViewオブジェクトはCocoaのほとんどの描画で使用されているオブジェクトです。しかし、描画プログラムやCADプログラムなど、数百から数千のグラフィック要素を扱う可能性のあるプログラムを設計する場合は、NSViewを継承したものではない、独自のカスタムグラフィック要素クラスを設計して使用することを検討します。オブジェクトのサイズという点から見た場合、NSViewオブジェクトには多数のインスタンスデータが付随します。独自に作成したカスタムクラスのグラフィック要素インスタンスを使用したほうが、“軽量”でありながら、単独のNSViewオブジェクトでそれらの要素を描画するのに必要となるすべての情報を保持できる可能性があります。



< Previous PageNext Page >


Last updated: 2006-05-23




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
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