実装copyWithZone:
に問題がある小さなクラス階層があります。NSCopying のドキュメントを読みましたが、正しい答えが見つかりません。
ShapeとSquareの 2 つのクラスを使用します。正方形は次のように定義されます。
@interface Square : Shape
そこに驚きはありません。各クラスには1 つのプロパティがあり、Shape には "sides" int があり、Square には "width" int があります。メソッドは以下のcopyWithZone:
とおりです。
形
- (id)copyWithZone:(NSZone *)zone {
Shape *s = [[Shape alloc] init];
s.sides = self.sides;
return s;
}
四角
- (id)copyWithZone:(NSZone *)zone {
Square *s = (Square *)[super copyWithZone:zone];
s.width = self.width;
return s;
}
ドキュメントを見ると、これが「正しい」方法のようです。
そうではない。
copyWithZone:
メソッドによって返される Square の width プロパティを設定またはアクセスしようとすると、次のようなエラーで失敗します。
2010-12-17 11:55:35.441 Hierarchy[22617:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Shape setWidth:]: unrecognized selector sent to instance 0x10010c970'
[super copyWithZone:zone];
Square メソッドを呼び出すと、実際には Shape が返されます。そのメソッドで width プロパティを設定することさえ許可されているのは奇跡です。
そうは言っても、スーパークラスの変数をコピーする責任を負わせないように、サブクラスにNSCopying を実装するにはどうすればよいでしょうか?