OC中对象的复制:二

看官们,我们在前面章回中介绍了OC中对象的复制,本章回中将继续介绍这方面的知识。
在上一章回中我们介绍了什么是复制以及如何进行复制。本章回中将介绍复制背后的原理和复制操作的原则。

复制的原理

我们通过复制操作的两个方法(copy和mutableCopy)进行复制操作时本质上是在调用`copyWithZone`和`mutableCopyWithZone`这两个方法.这两个方法是`NSCopying`和`NSMutableCopying`协议中的方法,而NSObject类实现了这两个协议并且重写了协议中的这两个方法。因此,我们在自己定义的类中重写这两个方法就可以实现复制操作。如果不重写这两个方法就进行复制操作,那么会导致运行时发生异常。下面是重写方法的示例代码。
 

-(id) copyWithZone:(NSZone *)zone
{
    NSLog(@"copying");
    //给各个属性赋值
}

-(id) mutableCopyWithZone:(NSZone *)zone
{
    NSLog(@"mutable copying");
    //给各个属性赋值
}

对于OC中的类以及Foundation框架中提供的类,我们可以直接使用copy方法来实现复制操作,因为这些类已经重写了`copyWithZone`和`mutableCopyWithZone`这两个方法。

复制的原则


这里说的原则主要有两个方面,一方面指深浅复制,另一方面指新复制出来的对象是否可以被修改。

  1. 对于自定义的类,我们的原则是:使用深复制并且复制出来的新对象可以被修改。也就是说不管使用copy方法还是mutableCopy方法,复制操作都是深复制,复制出来的对象都可以被修改。
  2. 对于OC中的类,如果类的对象是不可变的(比如NSString),copy方法是浅复制,复制出来的对象不可以被修改。 mutableCopy方法是深复制,复制出来的对象可以被修改。
  3. 对于OC中的类,如果类的对象是可变的(比如NSMutableString),copy方法和mutableCopy方法都是深复制,复制出来的对象都可经被修改。


对于使用等号进行赋值操作,它相当于浅复制,不管被复制的对象是否可变,它只是复制一个引用并没有创建新的对象。

对于自定义的类,在自定义类中实现复制操作的方法时需要遵守刚才说过的原则。对于OC中的类,复制操作的方法已经实现,我们可以通过代码来验证这些方法执行的原则。下面是一个示例代码,请大家参考:
 


#include <Foundation/Foundation.h>

@interface Book : NSObject
    @property (nonatomic,readwrite,strong) NSString *name;
    @property (nonatomic,readwrite,strong) NSMutableString *group;
    @property (nonatomic,readwrite,copy) Book* test;
    @property (nonatomic,readwrite) int price;

    -(void) show;
@end

@implementation Book
    @synthesize name;
    @synthesize price;
    @synthesize group;
    @synthesize test;

    -(void) show
    {
        NSLog(@"----Book Inof----");
        NSLog(@"name: %@ -- %p",name,name);
        NSLog(@"group: %@ -- %p",group,group);
        NSLog(@"test: %@ -- %p",test,test);
        NSLog(@"price: %d" ,price);
        NSLog(@"-----------------");
    }

//自己定义copy方法,其原则是深复制。使用mutableCopy方法实现深复制
-(id) copyWithZone:(NSZone *)zone
{
    NSLog(@"copying");
    Book *obj = [[[self class] allocWithZone:zone] init];

    obj.name = [self.name mutableCopy];
    obj.group = [self.group mutableCopy];
    obj.test = [self.test mutableCopy];
    obj.price = self.price;

    return obj;
}


-(id) mutableCopyWithZone:(NSZone *)zone
{
    NSLog(@"mutable copying");
    //直接使用交类的copy原则
    // id obj = [super mutableCopy];

    //直接使用自己的copy原则
    id obj = [self copy];

    return obj;
}

@end

int main()
{
    NSString *str1 = @"abc";
    NSString *str2 = [str1 copy];
    NSString *str3 = [str1 mutableCopy];

    //NSString对象,copy方法执行浅复制,mutableCopy方法执行深复制
    NSLog(@"string1 : %@ -- %p",str1,str1);
    NSLog(@"string2 : %@ -- %p",str2,str2);
    NSLog(@"string3 : %@ -- %p",str3,str3);

    NSArray *arr1 = [NSArray arrayWithObjects:@"aa",@"bb",@"cc",nil];
    NSArray *arr2 = [arr1 copy];
    NSArray *arr3 = [arr1 mutableCopy];

    //NSArray这类不可变对象,copy方法执行浅复制,mutableCopy方法执行深复制
    NSLog(@"array1: %@ -- %p",arr1,arr1);
    NSLog(@"array2: %@ -- %p",arr2,arr2);
    NSLog(@"array3: %@ -- %p",arr3,arr3);

    NSMutableArray *mutArr1 = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",nil];
    NSMutableArray *mutArr2 = [mutArr1 copy];
    NSMutableArray *mutArr3 = [mutArr1 mutableCopy];

    //NSMutableArray这类可变对象,copy方法和mutableCopy方法都执行深复制
    NSLog(@"mutabArray1: %@ -- %p",mutArr1,mutArr1);
    NSLog(@"mutabArray2: %@ -- %p",mutArr2,mutArr2);
    NSLog(@"mutabArray3: %@ -- %p",mutArr3,mutArr3);


    Book *b1 = [[Book alloc] init];
    [b1 setName:@"book1"];
    [b1 setPrice:1];
    [b1 setGroup:@"group1"];
    NSLog(@"Book1 --->");
    [b1 show];
    NSLog(@"Address: %p",b1);

    Book *b2 = [[Book alloc] init];
    //设置成copy属性后会调用类的copy方法
    [b2 setTest:b1];
    NSLog(@"Book2 --->");
    [b2 show];
}


在示例代码中演示了自定义类如何通过重写copy和mutalbeCopy方法来实现复制操作.同时也通过打印对象地址的方式演示了OC中类的复制原则,我们在相关地方都添加了注释,不过还是希望大家自己动手来实践,这样可以加深对这些复制原则的理解。


最后我们对本章回的内容做一个总结:

  • 1.复制操作表面是使用i`copy`和`mutableCopy`方法实现,但是本质上是通过`copyWithZone`和`mutableCopyWithZone`这两个方法实现的;
  • 2.自定义的类中需要实现`copyWithZone`和`mutableCopyWithZone`这两个方法,不然进行复制操作时会引发运行时异常;
  • 3.OC中提供的类已经实现了`copyWithZone`和`mutableCopyWithZone`这两个方法,我们直接进行复制操作就可以;
  • 4.我们需要明白OC提供类所遵守的复制原则,同时在自定义类时需要遵守自定义类的复制原则;

看官们,本章回的内容就介绍到这里,欲知后事如何且听下回分解!

上一篇:【三方件】Google Guava


下一篇:欧创芯原装OC 6700B升压型恒流驱动芯片,智能过温保护,内置 VDD 稳压管