最近は、新しいネタもないので、前回のネタを引っ張ってみる。NSArrayやNSDictionaryと言えば基本的なコンテナクラスとして、Cocoaでは頻繁に使われます。
// 要素の取得
id item = [items objectAtIndex: 1];
id name = [record valueForKey: @"name"];
// 要素の設定
[items replaceObjectAtIndex: 2 withObject: @"apple"];
[record setValue: @"red" forKey: @"name"];
しかし、要素の取得や設定が通常のメソッド呼び出しになっていて、コード書くのが少し面倒なうえ、あまり綺麗じゃない。できれば添字を使ってアクセスしたいところだ。
そんな願いはObjective-C++が叶えてくれる。まずは、前回出て来たIdクラスに添字の演算子オーバーロードを追加する。
class Id {
id object;
public:
Id() : object(nil) {}
Id(id obj) : object(obj) {}
operator id() { return object; }
// 添字演算子
Id operator [](NSUInteger index) {
return [object objectAtIndex: index];
}
};NSArrayについては、とりあえずこんな感じに書く。すると添字で要素の取得ができるようになる。
Id items = [NSArray arrayWithObjects:@"red", @"blue", @"Green", nil];
id item0 = items[0];
NSLog(@"item0: %@", item0); // item0: red
Id item1 = items[1];
NSLog(@"item1: %@", (id)item1); // item1: blue
NSInteger length2 = [items[2] length];
NSLog(@"item2 str length: %i", length2); // item2 str length: 5
Id colors = [NSArray arrayWithObjects:(id)items, nil];
id color = colors[0][1];
NSLog(@"color: %@", color); // color: blue
このように2次元配列にいたるまで期待どおりの動作をする。objectAtIndex:と比べれば、その差は歴然だ。この調子でoperator [](NSString* key)を定義すれば、NSDictionary (KVC)もサポートできるようになる。
と、ここまでは簡単なのだが、この調子で要素を設定できるようにするには、ひとひねり必要になる。
class Id {
...
KeyAccesser operator [](NSString* key) {
return KeyAccesser(object, key);
}
};
class KeyAccesser {
id object;
NSString* key;
public:
KeyAccesser(id obj, NSString* k) : object(obj), key(k) {}
// 添字
KeyAccesser operator [](NSString* k) {
return KeyAccesser([object valueForKey:key], k);
}
// 要素の取得
operator id() {
return [object valueForKey:key];
}
operator Id() {
return operator id();
}
// 要素の設定
void operator=(id obj) {
[object setValue:obj forKey:key];
}
};このように中間処理用のクラスを用意すればよい。これで要素の設定ができる。
Id record = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"red", @"color1",
@"blue", @"color2",
@"green", @"color3", nil];
id color1 = record[@"color1"];
NSLog(@"color1: %@", color1); // color1: red
Id color2 = record[@"color2"];
NSLog(@"color2: %@", (id)color2); // color2: blue
record[@"color3"] = @"yellow";
NSLog(@"color3: %@", (id)record[@"color3"]); // color3: yellow