【问题标题】:Correct way to implement NSCopying for class hiearchy为类层次结构实现 NSCopy 的正确方法
【发布时间】:2014-01-30 23:50:09
【问题描述】:

在两个类继承层次结构中实现 NSCopying 的最佳实践是什么?我想在副本上同时拥有 Square 和 Shape 属性的深层副本。

我有 3 个问题:

  1. 父类和子类是否都需要声明它们正在实现NSCopying,或者仅在基类上声明就足够了?
  2. 我看到有些人使用[instance copy] 而不是[instance copyWithZone:] 这只是一种偏好还是使用更正确:copyWithZone
  3. 复制数组时是否正确:newObj.list = [[NSArray alloc] initWithArray:self.list copyItems:YES];

这是我所拥有的:

@interface Shape : NSObject <NSCopying>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *sides;
@property (nonatomic, strong) NSArray *list;
@end

@implementation Shape 

- (id)copyWithZone:(NSZone *)zone {
    Shape *shape = [[[self class] allocWithZone:zone] init];

    // Is it correct to use copyWithZone: instead of copy? eg: [self.name copy]
    shape->_name = [self.name copyWithZone:zone];
    shape->_sides = [self.sides copyWithZone:zone];
    shape->_list = [[NSArray alloc] initWithArray:self.list copyItems:YES];

    return shape;
}
@end

// Does this class also need to declare <NSCopying>?
@interface Square : Shape 
@property (nonatomic, strong) NSString *color;
@property (nonatomic, strong) NSArray *corners;
@end

@implementation Square
- (id)copyWithZone:(NSZone *)zone {
    // Will this ensure a deep copy of the inherited properties?
    Square *square = [[[self class] allocWithZone:zone] init];

    square->_color = [self.color copyWithZone:zone];    
    square->_corners = [[NSArray alloc] initWithArray:self.corners copyItems:YES];

    return square;
}
@end

【问题讨论】:

  • 有点。我确实看到了这个问题,但它并没有回答我的所有问题。
  • 那么,请对您的问题更具体一些。你到底有什么不明白的?究竟有什么没有回答?

标签: objective-c


【解决方案1】:

父类和子类是否都需要声明它们正在实现 NSCopying 或者仅在基类上声明它就足够了?

这是风格问题。我一般不会再次声明NSCopying,但如果不是很明显,它可能会提供一点清晰度。

我看到有些人使用 [instance copy] 而不是 [instance copyWithZone:] 这只是一种偏好还是更正确的用法是:copyWithZone?

可以拨打copy。很长一段时间没有使用区域(我不相信 OS X 曾经使用过它们。)但是,您应该覆盖 copyWithZone:

在复制数组时,这样做是否正确:newObj.list = [[NSArray alloc] initWithArray:self.list copyItems:YES];

是的,这是必要的,但如果数组中的对象没有在它们的copyWithZone: 中实现深拷贝,这还不够。请注意,这调用copy,而不是mutableCopy。因此,如果您有一个可变数组数组,您将得到一个数组数组。如果你需要保持可变性,你必须自己打电话给mutableCopy

但是你犯了一个错误:

// Will this ensure a deep copy of the inherited properties?
Square *square = [[[self class] allocWithZone:zone] init];

不,你需要打电话:

Square *square = [super copy];

【讨论】:

  • 如果按照上述方式完成了复制,是否应该对现有对象和克隆对象进行后续 isEqual 检查返回 true?我需要实现自定义 isEqual 吗?
  • 您需要实现自定义-isEqual: 和自定义-hash。默认-isEqual 验证对象实际上是同一个对象。如果您实施-isEqual:,则必须始终实施-hash
猜你喜欢
  • 2015-05-14
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多