カプセル化を破るように見えるため、クラスがコレクション オブジェクトの可変プロパティを公開するパターンはほとんどありません。
それにもかかわらず、それが理にかなっている場合があります。たとえば、内部で管理されているコレクションの KVO プロキシを返すことができます ( KVC のmutableArrayValueForKey:
を使用)。
このような場合、getter をプロパティとして宣言するかプレーン メソッドとして宣言するかは問題ではありません。ただし、プロパティの場合は、プロパティであってはなりませんcopy
。
これをもう少し明確にするために、ここに例を示します。単一の public getter を宣言するクラスがあります。
@interface Foo : NSObject
@property (strong, readonly) NSMutableArray *publicBars;
@end
この実装は、次の名前のカプセル化された非公開の可変配列を管理します_bars
。
@implementation Foo
{
NSMutableArray *_bars;
}
この配列の要素は、KVC to-many アクセサーによって公開されます。
- (NSUInteger)countOfBars
{
return [_bars count];
}
- (id)objectInBarsAtIndex:(NSUInteger)idx
{
return _bars[idx];
}
- (void)insertObject:(id)object inBarsAtIndex:(NSUInteger)idx
{
if (_bars == nil)
_bars = [NSMutableArray array];
[_bars insertObject:object atIndex:idx];
}
- (void)removeObjectFromBarsAtIndex:(NSUInteger)idx
{
[_bars removeObjectAtIndex:idx];
}
ここで面白い部分があります:内部 ivar を公開せずに内部状態を反映および変更する KVC プロキシを返すことにより、パブリック プロパティを実装しています。上で定義した public アクセサーのみを使用して、内部配列を変更します。
- (NSMutableArray *)publicBars
{
return [self mutableArrayValueForKey:@"bars"];
}
@end
プロキシを使用して内部コレクションを変更できます。
Foo *foo = [[Foo alloc] init];
NSMutableArray *bars = foo.publicBars;
[bars addObject:@1];
[bars addObject:@2];
[bars removeObjectAtIndex:0];
// Now the internal _bars array is @[ @2 ].
Cocoa には、これと同様のパターンの実例があります。たとえば-[NSTextView textStorage]
、内部バッキング ストア (から派生したオブジェクトNSMutableAttributedString
) を返すものがあります。コレクション オブジェクトではありませんが、これはホスト オブジェクトであるテキスト ビューにミューテーションを渡すミュータブル オブジェクトです。