正确的方法来实现类层次结构的NSCopying

时间:2014-01-12 03:11:36

标签: objective-c

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

我有三个问题:

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

    这就是我所拥有的:

    @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
    

1 个答案:

答案 0 :(得分:0)

  

父类和子类都需要声明它们正在实现NSCopying,还是只足以在基类上声明它?

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

  

我见过有人使用[实例副本]而不是[实例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];