OC读书笔记——对象复制

对象复制

OC提供了两种复制对象的方法,一种为copy,另一种为mutableCopy。

copy和mutable方法

两种方法都是用来复制对象的副本,区别在于
1.copy方法的返回对象总是不可以修改的副本,如果对其进行修改,那么就会报错,即使复制的是NSMutableString类型的字符串,也不可以修改副本。
2.mutableCopy方法的返回对象是一个可以修改的脚本,即使复制的是不可变字符串NSString,副本也可以进行修改,并且修改副本时,不会影响原来的字符串。
下面的这两种方法的一些代码实现:

//
//  main.m
//  NStry
//
//  Created by 差不多先生 on 2021/6/5.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableString* book = [NSMutableString stringWithString:@"疯狂iOS讲义"];
        // 复制book字符串的可变副本
        NSMutableString* bookCopy = [book mutableCopy];
        // 修改副本对原字符串无任何影响
        [bookCopy replaceCharactersInRange:NSMakeRange(2, 3) withString:@"Android"];
        // 观察原字符串已经副本的变化
        NSLog(@"%@" , book);
        NSLog(@"%@" , bookCopy);
        NSString* str = @"fkit";
        // 复制不可变字符串的可变副本
        NSMutableString* strCopy = [str mutableCopy];
        // 1.向可变字符串后面追加字符串
        [strCopy appendString:@".org"];
        NSLog(@"%@" , strCopy);
        NSMutableString* bookCopy2 = [book copy];
        // [bookCopy2 appendString:@"aa"];
        return 0;
    }
}

在程序开始,对副本进行了修改,再分别打印原字符串和副本
得到的结果如下:
在这里插入图片描述
只是副本得到了修改。
最后注释的代码是报错的,因为他是使用了copy方法得到的字符串是不可以对其进行修改的。

NSString协议和NSMutableing协议

copy和mutableCopy方法复制对象十分方便,但他不可以复制自定义类。
这里定义了一个FKDog类。尝试复制自定义类。
接口部分:

#import <Foundation/Foundation.h>

@interface FKDog : NSObject
@property (nonatomic, strong) NSMutableString* name;
@property (nonatomic, assign) int age;

@end

主函数:

#import <Foundation/Foundation.h>
#import "FKDog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        FKDog* dog1 = [[FKDog alloc] init];
        dog1.name = [NSMutableString stringWithString:@"旺财"];
        dog1.age = 10;
        // FKDog* dog1Copy = [dog1 copy];
        return 0;
    }
}

上面这段代码中注视的语句会进行报错,Xcode显示错误为: Thread 1: "-[FKDog copyWithZone:]: unrecognized selector sent to instance 0x100709ae0"
提示找不到copyWithZone方法,其实NSObject中提供的copy方法返回的就是copyWithZone方法的返回值,但不支持复制自定义类,若要复制自定义类,则需要在接口部分实现NSString协议,并在实现部分加上copyWithCopy方法,代码如下
实现部分:

#import "FKDog.h"

@implementation FKDog
@synthesize  name = _name;
@synthesize age = _age;
- (id)copyWithZone:(NSZone*)zone {
    NSLog(@"--执行copyWithZone:--");
    FKDog* dog = [[[self class] allocWithZone:zone] init];
    dog.name = self.name;
    dog.age = self.age;
    return  dog;
}
@end

加入上述代码后,便可以实现使用copy方法对自定义类的复制。

FKDog* dog1Copy = [dog1 copy];
        dog1Copy.age = 12;
        dog1Copy.name = [NSMutableString stringWithString:@"snoopy"];

在上述的代码中,对复制的副本进行了修改,尽管我们使用了copy方法,按道理复制的对象应该不可以改变,但由于我们自定义的类没有不可变类,所以可以进行修改。
最后强调,如果重写父类时,其父类实现NSCopy协议并重写了copyWithZone:方法时,应该先使用父类的copy方法复制父类的成员变量再重写子类的方法,再对子类定义的成员变量赋值。
代码格式如下:

- (id)copyWithZone:(NSZone*)zone {
    id cpy = [super copy];
    // 对子类变量赋值
    ...........
    return cpy;
}

浅复制与深复制

在上面的代码中如下修改副本的值

 [dog1Copy.name replaceCharactersInRange:NSMakeRange(0, 2) withString:@"snoopy"];

再输出原字符串和副本,会发现他俩相同,这是因为在重写的方法中,只是让副本的name变量和原对象的name变量指向了同一个字符串,name存储的仅仅是地址,所以对其进行修改时,实际是对他实际指向的NSMutable字符串进行修改,输出的结果相同。
对于上述这种复制方式,称为浅复制:

程序仅仅复制了指针的地址,而并非指针指向的对象

深复制则与其完全不同,不仅会复制指向的对象,还会递归复制每个指针类型的属性,直到两个对象没有公用的部分。
采用深复制可以重写上面的copyWithZone:方法,代码如下:

- (id)copyWithZone:(NSZone*)zone {
    NSLog(@"--执行copyWithZone:--");
    FKDog* dog = [[[self class] allocWithZone:zone] init];
    // 将原对象的name实例变量赋值一份然后赋给新对象的name实例变量。
    dog.name = [self.name mutableCopy];
    dog.age = self.age;
    return  dog;
}

重写的方法并不是简单将原对象的属性赋给新对象,而是复制了一个新的可变副本赋值给新对象,这样就可以保证二者无公用部分,实现了深复制。
这样重新打印上面的两个对象,修改复制对象的值并不会影响原对象。
深复制的实现很复杂,尤其是当指针繁多的时候。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计项目).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值