5

同じように動作するNSArrayのすべてのメソッドを持つクラスが必要ですが、2つのメソッドが変更されています。

カスタムクラスでこれらの2つのメソッドをオーバーライドしたい:

1)countByEnumeratingWithState:objects:count:

2)objectAtIndex:

何時間も調査した後、それを行うための合理的な方法がわかりません。理由は次のとおりです。

  • すべてのNSArrayインスタンスで変更された動作が必要なわけではないため、categoryを使用したくありません。(さらに、警告をスローします)

  • すべての初期化子とすべてのarrayWith...メソッド+プリミティブメソッド+独自のストレージを実装したくない(この機能はすでにCocoaに実装されているためですよね?なぜ私はすべての機能を再実装するのでしょうか?すでにそこにあるクラス?)

  • カスタムクラスにNSObjectを継承させ、NSArrayをivarのストレージとして使用する場合、XcodeでプログラミングするときにすべてのNSArrayのメソッドを使用することはできません(NSArray ivarに転送できる場合でも)

  • method_setImplementation(...)を使用して、オンデマンドでメソッド実装を上書きすることに成功しましたが、実行時にクラスを動的に作成する方法を理解できません。これにより、前述の2つのメソッドのカスタム実装が作成されます。

あなたのアイデアを楽しみにしています!ありがとう

4

2 に答える 2

9

マントラ: 何かが難しい場合(または必要以上のコードが必要なように思われる場合)、デザインはiOS /OSXフレームワークのデザインプリンシパルに反している可能性があります。それはあなたのデザインを再考するためのより良い解決策を生み出すかもしれません。


元の質問に答えるために、NSArray(またはNSMutableArray)をサブクラス化する場合は、プリミティブメソッドを実装する必要があります。それ以上でもそれ以下でもありません。

プリミティブメソッドは@interface、クラス自体ので宣言されたメソッドです。すなわち:

@interface NSArray : NSObject
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
@end

そしてNSMutableArrayの場合:

@interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
@end

NSMutableArrayをサブクラス化し、上記の7つのメソッド(NSArrayからの2つも)を実装すると、メソッドが正しく実装されていると仮定して、可変配列を使用するすべてのAPIと互換性のあるNSMutableArrayサブクラスが得られます。

これは、クラスクラスターの設計方法によるものです。パブリッククラスは抽象的です。直接インスタンス化されることはありません。これらは、クラスのコア機能を含むプリミティブインターフェイスを提供し、プリミティブの観点から実装された他のすべての非プリミティブAPI(初期化子を除く、以下を参照)の具体的な実装を提供します。次に、具象、プライベート、サブクラスがすべてのプリミティブと一部の非プリミティブをオーバーライドして、特定の構成に最適な動作を提供します。

作業中のライブラリのNSArrayインスタンスが必要であり、ライブラリのユーザーに対して透過的に機能するようにしたい。つまり。それらは、通常のNSArrayを使用することと、私が提供する変更されたクラスを使用することの間に違いはないはずです。つまり。これはストレージの問題であり、エンドユーザーは気にせず、インターフェイスはNSArrayと同じままである必要があります。したがって、その時点ですべてのinitメソッドを失うことは実際にはオプションではありません。

初期化メソッドは、へのプリミティブインターフェイスの一部ではありませんNSArray。ドキュメントで定義されているように、「NSArray/と互換性のあるクラスを作成する」以上の要件を追加しています。NSMutableArrayそれは何も悪いことではなく、ただ指摘するだけです。

これが当てはまる理由は、コレクションクラスをサブクラス化して、説明する種類のビジネスロジックを提供することは非常にまれだからです。コレクションの動作は非常に一般的ですが、コレクションの動作を条件付けするビジネスロジックは、モデルレイヤーオブジェクトグラフ全体を管理するクラスで実行されます。

init*本当にこれを実行したい場合は、必要に応じてラップされた汎用インスタンスを呼び出して、必要なメソッドの実装を提供します。イニシャライザーの実装については、そうすることで多くを失うことになるほど特別なことは何もありません。

それらすべてを実装する必要もありません。1つまたは2つを実装し、残りの部分に説明的な例外を@throwします。

var-argsを受け入れるものを転送することにした場合、va_listを受け入れるメソッドがないため、直接転送することはできません。代わりに、引数のva_listを言語配列(つまりid[] foo = malloc(... * sizeof(id));)に変換して、に渡しinitWithObjects:count:ます。

他のいくつかのコメント:

  • [サブクラスで完全なNS*Arrayインターフェイスを提供する]ことは、一般的なパターンではなく、フレームワークの設計者がそれをサポートする設計を作成する必要がないと考えたため、難しいようです。プリミティブコレクションレベルでのカスタム動作は、ほとんどの場合、オブジェクトグラフ内のより高いレベルでより適切に実装されます。 ほとんどの場合。

  • method_setImplementation()と動的クラスの作成は学術的に興味深いものですが、解決策になることはほとんどありません。明らかに、NSArrayまたはNSMutableArrayクラス(または具体的な実装クラス)をいじくり回すと、標準の動作に依存する残りのフレームワークが爆破されます。それを超えて、それは、Objective-Cでの使用を実際に意図していない動的なOO構成のパターンです。維持するのはお尻の痛みになります。

于 2012-12-18T16:53:59.860 に答える
0

NSArrayをサブクラス化する代わりに、NSArrayを含むNSObjectに基づいて新しいクラスを作成してみませんか?

次に、NSArrayのすべての関数を使用して、それを使用してカスタムアクションを実行する独自のメソッドを追加できますか?

または、NSArrayが必要ですか?

于 2012-12-18T09:00:43.350 に答える