私はNSArrayがまさにそのようなものであることを読んでいました。重いですね。私の机の上にはObjective-C、Cocoa、およびCについての本当に太った本が7冊あります。それらのどれもクラスクラスターについてまったく言及していません。少なくとも、本の後ろにある索引では見つけることができません。それでそれは何ですか?
私はNSArrayがまさにそのようなものであることを読んでいました。重いですね。私の机の上にはObjective-C、Cocoa、およびCについての本当に太った本が7冊あります。それらのどれもクラスクラスターについてまったく言及していません。少なくとも、本の後ろにある索引では見つけることができません。それでそれは何ですか?
回答:
Appleのドキュメントから...。要するに、これはFoundationフレームワークで使用されるデザインパターンです。そのため、ObjCの本には記載されていません。
クラスクラスターは、パブリックな抽象スーパークラスの下に、多くのプライベートな具象サブクラスをグループ化するアーキテクチャです。このようにクラスをグループ化すると、一般に公開されているアーキテクチャのみを表示するユーザーに、簡略化されたインターフェースが提供されます。
Steveが参照したCDPの内容はわかりませんが、基本的にはObjective-Cクラスクラスターは、抽象的なFactoryパターンの実装をサポートする構造です。
アイデアは単純です:あなたは、最小限の記述で、満たすクラスタ家族の行動は、工場(クラスタ)インターフェースによって記述することをファクトリオブジェクトの特定の具体的なインスタンスを製造して返す、という工場(クラスタ)のインターフェイスを提供したいです。
簡単な具体例:この例は、特定の笑いタイプの具体的なクラス(Guffaw、Giggleなど)を生成するLaughファクトリーを提供します。笑いのinitWithLaughter:メソッドに注意してください。
Laugh.hで:
#define kLaughWithGuffaw 1
#define kLaughWithGiggle 2
@interface Laugh: NSObject {}
- (Laugh *) initWithLaughter:(NSUInteger) laughterType;
- (void) laugh;
@end
Laugh.mで:
@interface Guffaws:Laugh {}
- (void) laugh;
@end
@interface Giggles:Laugh {}
- (void) laugh;
@end
@implementation Laugh
- (Laugh *) initWithLaughter:(NSUInteger) laugherType {
id instanceReturn=nil;
; // Removed for ARC [self release]
if ( laughterType == kLaughWithGuffaw )
instanceReturn = [[Guffaws alloc]init];
else if( laughterType == kLaughWithGiggle )
instanceReturn = [[Giggles alloc]init];
else
; // deal with this
return instanceReturn;
}
- (void) laugh {
NSLog(@"Humbug");
}
@end
@implementation Guffaws
- (void) laugh {
NSLog(@"OH HA HA HOWAH HA HA HA");
}
@end
@implementation Giggles
- (void) laugh {
NSLog(@"Tee hee");
}
@end
.m-file
。
init
メソッド内で自分自身を解放し、別のものを返すことはどのくらい安全ですか?これを行うAppleのコード例はありますか?(2)また、のようなコードでインスタンスを作成していると考えられ[[Laugh alloc] initWithLaughter:kLaughWithGiggle]
ます。Laugh
この呼び出しの直後に解放されるため、が不必要に割り当てられていることに注意してください。[Laugh laughWithLaughter:kLaughWithGiggle]
上記の問題1と2を回避しながら、プライベートサブクラスのすべての利点を提供するようなクラスメソッドを作成できるのに、なぜこのようにするのですか?
+alloc
は、さまざまな-initWith:
メソッドを実装するシングルトンファクトリクラスを返します。次に、ファクトリクラスの-initWith:
メソッドは、必要に応じて、指定されたメソッドパラメータに基づいて具象サブクラスの割り当てと初期化を行うか、場合によっては何も割り当てないことがあります(など-[NSString initWithString:]
)。あなたはの戻り値で検査することによって、それを試すことができ+[NSString alloc]
、+[NSArray alloc]
など
用語集のクラスターの498ページにあるスティーブンコチャンによる目的cのプログラミングから:
プライベートコンクリートサブクラスのセットをグループ化する抽象クラス。抽象クラスを通じてユーザーに簡略化されたインターフェースを提供します。
クラスクラスターは、具体的なプライベートサブクラス実装のグループに単一のパブリックインターフェイスを提供します。Objective-Cプログラマーはクラスクラスターを頻繁に使用し、ほとんど実現しません。これがクラスクラスターの要点です。クラスクラスターの仕事は、パブリックインターフェイスの背後にある実装の詳細の複雑さを隠すことです。
Foundationクラスの多くは、NSString、NSArray、NSDictionary、NSNumberなどのクラスクラスターです。[NSString stringWithFormat:]
クラスクラスターを呼び出すと、NSString
インターフェイスを実装する具体的なクラスが提供されます。それができるNSConcreteString
、NSCFString
、NSFooBarString
、など、どのクラスクラスタを使用すると、コンストラクタに基づくか、呼び出しと引数されている初期化子されいます。
このため、クラスクラスターは、Objective-Cプログラミングで最も強力な概念の1つです。
他の言語を使用している場合は、Gang of Fourパターンに精通している可能性があります。クラスクラスターには、抽象ファクトリとファサードパターンの両方の要素があります。
Appleの公開ドキュメントは、クラスクラスター(およびそれらを実装および拡張する方法)を非常に広範囲にカバーしています。残念ながら、多くのiOS開発者にとって、これと他のCocoa固有のパターンは盲点であることがわかりました。
NSArrayクラスのクラスターは「重い」ものではありません。これは、特定の実装をコードが認識したり気にかけたりせずに、配列クラスの任意の数の実装を使用する方法です。内部的には、NSArrayの具体的なサブクラスがあり、それらは、大規模なスパース配列や、コンパイル時に既知の特定の数の要素を含む配列など、さまざまなユースケースに適しています。
NSArray、NSString、およびNSNumberは、最も頻繁に遭遇するクラスクラスターです。
[myArray isKindOfClass:[NSMutableArray class]]
YES が返されないはずですが、返されませんか?