Objective c 实现类层次结构复制的正确方法

Objective c 实现类层次结构复制的正确方法,objective-c,Objective C,跨两类继承层次结构实现NSCopying的最佳实践是什么?我想要一个正方形和形状属性的深度副本 我有三个问题: 父类和子类都需要声明它们正在实现NSCopying,还是只在基类上声明就足够了 我见过一些人使用[instance copy]而不是[instance copyWithZone:这只是一种偏好,还是更正确地使用:copyWithZone 复制数组时,是否正确执行以下操作:newObj.list=[[NSArray alloc]initWithArray:self.list copyIt

跨两类继承层次结构实现NSCopying的最佳实践是什么?我想要一个正方形和形状属性的深度副本

我有三个问题:

  • 父类和子类都需要声明它们正在实现
    NSCopying
    ,还是只在基类上声明就足够了
  • 我见过一些人使用
    [instance copy]
    而不是
    [instance copyWithZone:
    这只是一种偏好,还是更正确地使用:
    copyWithZone
  • 复制数组时,是否正确执行以下操作:
    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
    
    @接口形状:NSObject
    @属性(非原子,强)NSString*名称;
    @属性(非原子,强)NSN数*边;
    @属性(非原子,强)NSArray*列表;
    @结束
    @实现形状
    -(id)copyWithZone:(NSZone*)区{
    Shape*Shape=[[self class]allocWithZone:zone]init];
    //使用copyWithZone:而不是copy正确吗?例如:[self.name copy]
    shape->_name=[self.name copyWithZone:zone];
    形状->_边=[self.sides copyWithZone:zone];
    shape->_list=[[NSArray alloc]initWithArray:self.list copyItems:YES];
    返回形状;
    }
    @结束
    //这个类也需要声明吗?
    @界面正方形:形状
    @属性(非原子,强)NSString*颜色;
    @属性(非原子,强)NSArray*角;
    @结束
    @实施广场
    -(id)copyWithZone:(NSZone*)区{
    //这将确保继承属性的深度副本吗?
    Square*Square=[[self class]allocWithZone:zone]init];
    正方形->_color=[self.color copyWithZone:zone];
    square->_corners=[[NSArray alloc]initWithArray:self.corners copyItems:YES];
    返回广场;
    }
    @结束
    
    父类和子类是否都需要声明它们正在实现NSCopying,或者仅在基类上声明就足够了

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

    我见过一些人使用[instance copy]而不是[instance copyWithZone:]这只是一种偏好还是使用:copyWithZone更正确

    可以调用
    copy
    。区域已经很久没有被使用了(我不相信OSX曾经使用过它们)。但是,您应该覆盖
    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];
    

    可能是某种类型的重复。我确实看到了那个问题,但它并没有回答我所有的问题。那么,请更具体地回答你的问题。你到底不明白什么?有什么问题没有得到回答?如果按照前面提到的方式进行复制,那么对现有对象和克隆对象的后续等质量检查是否应该返回true?我需要实现一个自定义的isEqual吗?您需要实现一个自定义的
    -isEqual:
    和一个自定义的
    -hash
    。默认的
    -isEqual
    验证对象实际上是同一个对象。如果实现了
    -isEqual:
    ,则必须始终实现
    -hash