5

Objective-cでは?

クラスを作ってもらい、ファーストクラスのような別のクラスが欲しいと思いました。プロトコルを使用して両方のクラスがそのプロトコルをサポートしていることを確認する必要がありますか、それとも親クラスを作成して2つのクラスがその1つのクラスから継承することを決定する必要がありますか?

ノート:

クラスは、Business、Catalog、AddressAnnotation(現在はビジネスのみでのみ機能)およびAddressAnnotationView(現在はビジネスのみでのみ機能)です。同じことがカタログでも機能するようにしたい。アノテーションがまとめられたときに管理するBGGoogleMapCacheForAllAnnotationsもあります(これで、カタログとビジネスの両方のAddressAnnotationを処理できるようになります。また、親クラスに変換したいBGGoogleMapViewControllerもあります。

4

2 に答える 2

8

プロトコルを使用する場合は、両方のクラスタイプで共有されるメソッドを2回定義する必要があります。プロトコルは通常、セキュリティを追加して間違いを犯しにくくするために、またはクラス階層にすでに埋め込まれている複数のクラスが共通のメソッドを共有し、この共有を文書化する必要がある場合に、委任パターンなどの特定のパターン用に予約されていますどういうわけか。あるクラスを別のクラスのより特殊なバージョンとして表すことができる場合は、継承する必要があります。

たとえばVehicle、ゲーム内に、移動など、あらゆる種類の操作を行う方法を知っているクラスがあるとします。クラスを作成したい場合はCar、おそらくクラスをサブクラス化してVehicle、そのすべてのメソッド実装を継承できるようにします。それらを大規模に利用するか、独自のバージョンのメソッドを実装します。おそらく、スーパークラスの実装を呼び出す前に、サブクラスに固有のタスクを実行します。サブクラス化は、スーパークラスを何らかの方法で変更しながら、その特性と動作を継承する場合に使用します。これは、インスタンス変数などの追加データをクラスに追加する必要がある場合に特に当てはまります。これは、カテゴリでは追加できないためです(ただし、Class Extension、多くの場合、一種のプライベートインターフェイスと見なされます)。一般に、サブクラスには、結果としてスーパークラスよりも特殊な目的があります。

プロトコルはまさにそのプロトコルです。それらは、あなたが何かを台無しにしたり忘れたりするのを防ぎ、すべてのオブジェクトが想定どおりに動作することを保証し、クラスが想定どおりに動作していないときにコンパイラ警告をトリガーするためにあります。これは、委任などのパターンにとって重要です。これは、カプセル化を解除して委任がどのタイプのオブジェクトであるかを知る以外に、委任が必要なメソッドを実装することを保証する唯一の方法だからです。たとえば、私のプロジェクトの1つからの以下のコードを見てください。

//SGSprite.h
@protocol SGSpriteDelegate
    - (BOOL) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
@end

@interface SGSprite : NSObject
@property (nonatomic, assign) id<SGSpriteDelegate> delegate;
@end

//SGViewController.h
@interface SGViewController : UIViewController <SGSpriteDelegate>
    //...dreadfully boring stuff
@end

多くのクラスは、SGSpriteテクスチャ2Dクワッドをレンダリングするために私のクラスを利用しています。スプライトがアニメーションの特定のフレームに到達したことを知る必要がある場合があるため、SGSpriteインスタンスはデリゲートのメソッドを呼び出して、特定のフレームに到達したことを通知する必要があります。このクラスのインスタンスへのデリゲートがこのメソッドを実装することを保証する唯一の方法、そして実際、誰かがデリゲートとしてではないオブジェクトを割り当てようとした場合に警告する唯一の方法は、プロトコルを使用することです。デリゲートを単純にプレーンidにすると、デリゲートでこのメソッドを呼び出すたびに警告が表示されます。これは、その実装が見つからないためです。一方、デリゲートのヘッダーをインポートするか、デリゲートを静的に入力すると、クラス十分にカプセル化されていません。

ほとんどの場合、技術的にプロトコルは必要ありません。通常はプロトコルに準拠するすべてのクラスで、プロトコルなしですべてのメソッドを定義でき、すべてが正常に機能します。ただし、これらの一般的な方法は文書化されていません。したがって、特定のクラスまたは匿名オブジェクトが実装に必要なメソッドを実装していることを知っているというセキュリティを超えて、何が何をどのように実行するかをすばやく判断することもできます。プロトコルは、クラスまたはクラスのインスタンスが何らかのメソッドを実装することを保証する必要がある場合、特にオブジェクトのタイプがクラスをカプセル化したままにする必要がない場合に使用します。

于 2013-02-14T04:37:07.593 に答える
3

その決定に影響を与える可能性のある多くの要因があります。一つには、他のクラスが「ファーストクラスのように」と言うとき、それはどういう意味ですか? 同じことの 90% をまったく同じ方法で行うということですか? 彼らは同じ種類のことをたくさんしますが、それぞれがわずかに異なる方法で行うということですか?

最初のクラスの既存のメソッドの多くが 2 番目のクラスでそのまま、またはほとんど変更せずに機能する場合、サブクラス化により、これらのメソッドをすべて「無料」で取得できるため、違いに集中できます。ただし、ほとんどのコードを書き直す必要があり、2 つのクラスを同様のアクションを実行するものとして定義したい場合は、プロトコルの方が理にかなっている可能性があります。

私は個人的にサブクラス化のみを使用してきました。主な理由は、コードでプロトコルが意味を成す状況に遭遇したことがないためです。もちろん、しばらくすると、意識的な決定というよりも習慣から外れています。アプリを Core Data を使用するように変換し始めたとき、Core Data は継承された属性と関係を持つサブエンティティを作成する機能を提供するため、サブクラス化は非常にうまく適合しました。これにより、概念的に把握しやすくなりました。

現在のコードについて考えると、既にサブクラス化 (NSObject、ビュー コントローラーなど) を行っており、プロトコル (NSCoding、ビュー デリゲートなど) を使用している可能性があります。これらの既存のクラスとプロトコルをどのように使用するか、またそれらのユース ケースが独自のクラスにどのように適用されるかを考えてください。

于 2013-02-14T04:33:06.213 に答える