You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Objective-C中实现深拷贝?附Patient与Symptoms类示例

实现Patient和Symptoms类的深拷贝方案

要实现这两个类的深拷贝,核心是确保自定义对象类型的属性(比如Patient里的symptoms)被真正复制出一个新实例,而不是只拷贝指针引用。下面咱们一步步来实现:

1. 先实现Symptoms类的NSCopying协议

Symptoms的属性都是基础数据类型(CGFloat、BOOL),没有嵌套的自定义对象,所以实现起来比较直接:

@interface Symptoms () <NSCopying>
@end

@implementation Symptoms

- (nonnull id)copyWithZone:(NSZone *)zone {
    // 创建当前类的新实例
    Symptoms *copiedSymptoms = [[[self class] allocWithZone:zone] init];
    
    // 直接复制基础类型属性
    copiedSymptoms.temperature = self.temperature;
    copiedSymptoms.headache = self.headache;
    copiedSymptoms.stomach_ache = self.stomach_ache;
    
    return copiedSymptoms;
}

@end

这里因为所有属性都是值类型,直接赋值就完成了深拷贝——新的Symptoms实例和原实例完全独立,修改其中一个不会影响另一个。

2. 实现Patient类的NSCopying协议

Patient里包含了Symptoms这个自定义对象,这是深拷贝的关键节点,必须注意:

// 先确保Patient类声明遵循NSCopying
@interface Patient () <NSCopying>
@end

@implementation Patient

- (nonnull id)copyWithZone:(NSZone *)zone {
    Patient *copiedPatient = [[[self class] allocWithZone:zone] init];
    
    // 1. NSString是不可变对象,直接赋值或调用copy都可以(效果一致)
    copiedPatient.name = self.name;
    
    // 2. 重点!Symptoms是自定义对象,必须调用它的copy方法来创建新实例,实现深拷贝
    copiedPatient.symptoms = [self.symptoms copy];
    
    // 3. Status是assign类型的枚举,直接赋值即可
    copiedPatient.status = self.status;
    
    // 4. delegate是weak引用,通常深拷贝不会复制这个属性(因为它属于外部对象,拷贝后的实例不需要继承原实例的代理关系)
    copiedPatient.delegate = nil; // 或者根据业务需求决定是否保留,一般设为nil
    
    return copiedPatient;
}

@end

关键要点说明

  • 自定义对象必须调用copy:如果Patient的symptoms直接赋值copiedPatient.symptoms = self.symptoms,那就是浅拷贝——两个Patient实例会共享同一个Symptoms对象,修改其中一个的症状,另一个也会跟着变,这就违背了深拷贝的初衷。
  • 不可变对象(如NSString):因为不可变,所以直接赋值和copy的效果一样,不会有引用共享的问题。
  • weak属性处理:delegate是弱引用,拷贝后的新Patient实例通常不需要继承原实例的代理,所以设为nil是合理的;如果有特殊业务需求,再考虑其他处理方式。

内容的提问来源于stack exchange,提问作者Arseniy Spiridonov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:16:00