objective-c - 在子类的子类中实现 NSCopying

标签 objective-c xcode memory-management hierarchy nscopying

我有一个小类层次结构,我在实现 copyWithZone: 时遇到了问题。我已阅读 NSCopying 文档,但找不到正确的答案。

参加两个类(class):ShapeSquare。正方形定义为:

@interface Square : Shape

这并不奇怪。每个类都有一个属性,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 的宽度属性,它将失败并出现类似于以下的错误:

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'

在 Square 方法中调用 [super copyWithZone:zone]; 实际上返回一个 Shape。您甚至可以在该方法中设置 width 属性,这真是一个奇迹。

话虽如此,如何以一种不让子类负责复制其父类(super class)变量的方式为子类实现 NSCopying

最佳答案

你在问完之后马上意识到的事情之一......

copyWithZone: 在父类(super class) (Shape) 中的实现不应该假设它是一个 Shape。因此,不要像我上面提到的那样错误:

- (id)copyWithZone:(NSZone *)zone {
    Shape *s = [[Shape allocWithZone:zone] init];
    s.sides = self.sides;
    return s;
}

你应该改用:

- (id)copyWithZone:(NSZone *)zone {
    Shape *s = [[[self class] allocWithZone:zone] init]; // <-- NOTE CHANGE
    s.sides = self.sides;
    return s;
}

关于objective-c - 在子类的子类中实现 NSCopying,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4472904/

相关文章:

ios - 用户定义的运行时属性是否仅适用于自定义类?

iphone - Storyboard中的问题 : Other views at the top of the table view are not visable

ios - Xcode iOS 照片库应用程序

objective-c - 使用 ARC,如何正确设置具有副作用的属性?

ios - 以编程方式将UILabel文本对齐到底部?

xcode - 将现有的实现文件添加到 Xcode 项目将不起作用

iOS:CNContactPicker didSelect - 如何确定所选属性的类型?

c++ - vector <T *> 析构函数

memory-management - vmalloc() 是否仅在 32 位 x86 上从 ZONE_HIGHMEM 获取内存?

php - IOS Web 服务推荐