NSObject对象是否可以copy自己

NSObject类没有实现NSCopying或者NSMutableCopying协议,但是却有copy以及mutableCopy实例方法。然而,如果用NSObject对象直接调用其copy或者mutableCopy方法,会报错。也就是说,NSObject对象无法copy自己。

既然NSObject类没有实现copy协议,那为什么还要有对应的copy和mutableCopy方法呢?

因为NSObject类的copy和mutableCopy方法里面分别都会调用copyWithZone以及mutableCopyWithZone,那么所有继承自NSObject类并且实现NSCopying或者NSMutableCopying协议的类的拷贝行为,都可以简化为调用copy或者mutableCopy方法。

实现copy协议时,何时需要调用[super copyWithZone:zone]

1 类直接继承自NSObject,无需调用[super copyWithZone:zone]

@interface X : NSObject <NSCopying>

@property (assign, nonatomic) NSInteger i;

@end

@implementation X

- (id)copyWithZone:(NSZone *)zone {
X *x = [[[self class] alloc] init]; //没有调用[super copyWithZone:zone]
x.i = self.i; return x;
}

类X直接继承自NSObject,由于NSObject没有实现copy协议,因此如果调用[super copyWithZone:zone]编译器会报错:

No visible @interface for 'NSObject' declares the selector 'copyWithZone:'

2 父类实现了copy协议,子类也实现了copy协议,子类需要调用[super copyWithZone:zone]

@interface Y : X <NSCopying>

@property (assign, nonatomic) NSInteger j;

@end

@implementation Y

- (id)copyWithZone:(NSZone *)zone {
Y *y = [super copyWithZone:zone]; //子类调用[super copyWithZone:zone]
y.j = self.j; return y;
} @end

子类通过调用[super copyWithZone:zone]方法来分配内存,并且拷贝父类中的实例变量,子类自己的实例变量需要自己拷贝

3 父类没有实现copy协议,子类实现了copy协议,子类无需调用[super copyWithZone:zone]

如果上面的例子中类X没有实现copy协议,而子类Y实现了copy协议,这种情况类似与情形1,子类Y无需调用[super copyWithZone:zone]

- (id)copyWithZone:(NSZone *)zone {
Y *y = [[[self class] alloc] init]; //子类无需调用[super copyWithZone:zone]
y.i = self.i;
y.j = self.j; return y;
}

但是这种时候子类需要自己copy父类中的实例变量。

为何在copyWithZone方法中要调用[[[self class] alloc] init]来分配内存

在上面的情形2中,子类Y继承子父类X,如果父类X的copyWithZone方法使用:

[[X alloc] init];

来分配内存,那么在子类Y copy的时候就会出现内存分配的问题。

因为在子类Y的copyWithZone的方法里面调用会调用父类[super copyWithZone:zone]方法,而父类中[[X alloc] init]创建的对象分配的内存大小和类X的实例一样大,而这里是要拷贝Y,类Y继承了X的实例变量,同时也有自己的实例变量,所以类Y的实例所占用的内存明显比类X的实例大,因此,这里会导致内存分配错误。而父类X中如果使用[[[self class] alloc] init]来创建对象分配内存,在运行时self class就是类Y,这样保证了内存分配正确。

propery中的copy属性

这里只需记住,property的copy只会产生copyWithZone的调用,而不会产生mutableCopyWithZone的调用。

Objective-C中的copy协议的更多相关文章

  1. OC中的copy

    copy的概念 Copy的字面意思是"复制"."拷贝",是一个产生副本的过程 对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容,常 ...

  2. 理解Objective C 中id

    什么是id,与void *的区别 id在Objective C中是一个类型,一个complier所认可的Objective C类型,跟void *是不一样的,比如一个 id userName, 和vo ...

  3. 浅谈Objective—C中的面向对象特性

    Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...

  4. Android 中多点触摸协议

    http://blog.csdn.net/zuosifengli/article/details/7398661 Android 中多点触摸协议: 参考: http://www.kernel.org/ ...

  5. C# WCF学习笔记(二)终结点地址与WCF寻址(Endpoint Address and WCF Addressing) WCF中的传输协议

    URI的全称是 Uniform Rosource Identifire(统一资源标识),它唯一标识一个确定的网绐资源,同时也表示资源所处的位置及访问的方式(资源访问所用的网络协议). 对于Endpoi ...

  6. 详解Objective-C中委托和协议

    Objective-C委托和协议本没有任何关系,协议如前所述,就是起到C++中纯虚类的作用,对于“委托”则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可以实现委托. AD: ...

  7. c#中命令copy已退出,返回值为1

    c#中命令copy已退出,返回值为1 本正经的道:董姐刚才你说的修心养性其中的'修心'我 有孕在身刚好由戴梦瑶顶替了她的位置按照的指示 ╋旆呆 湎术葶页 邾箕砜笳 烦璜卿廑 奶奶个腿儿的等下次非让你 ...

  8. PHP中的http协议

    PHP中的http协议 http协议基本组成 报文:用于Http协议交互的信息 请求行:包括请求的方法,URL和HTTP协议版本 状态行:包括响应结果的状态码,状态描述和Http版本 首部字段:包括请 ...

  9. Dockerfile 中的 COPY 与 ADD 命令

    Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令的基本功能,以及其异同点,然后总结其各自适合的应用场景. Build 上下文的概念 在使用 docker ...

随机推荐

  1. 零基础创建RCP工程

    一.环境搭建 1. 安装java jdk,我选择的是jdk 1.7版本,配置环境变量: 2. 下载并安装java EE: 二.创建工程 1. 打开File-> New ->other -& ...

  2. GET异步 请求图片步骤

    - (IBAction)getImage:(id)sender { //1,准备URL NSString *str = @"http://e.hiphotos.baidu.com/image ...

  3. 一个正整数N,拆成任意个正整数之和,怎样使这些数的乘积最大

    网上看到了如标题所示的题目,就开始想如果用程序来算的话,那么它的算法是怎样的. 自己想了半天,第一感觉要用递归, 如先算出 当 n=1 max=1 当 n=2 max=1 当 n=3 max=2 .. ...

  4. ASP.NET 表单认证与角色授权

    参考 : http://hi.baidu.com/iykqqlpugocfnqe/item/e132329bdea22acbb6253105  ASP.NET中处理请求的流程图 http://www. ...

  5. hdu Children’s Queue

    http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=3&sectionid=1&problemid=10 #incl ...

  6. 什么是PWM、PFM及VFM

    做电源设计的大都知道PWM和PFM这两个概念.而VFM模式是在大功率輸出時為PWM模式在輕負載輸出時變為PFM模式的一種混合開關模式.目前开关电源的控制技术主要就是这三种:1.脉冲宽度调制器(PWM) ...

  7. C# 在腾讯的发展(作者是微软连续10年的MVP)

    本文首发我的微信公众号"dotnet跨平台", 内容得到大家热烈的欢迎,全文重新发布在博客,欢迎转载,请注明出处. .NET 主要的开发语言是 C# , .NET 平台泛指遵循EC ...

  8. Windows服务器Pyton辅助运维--03.安装Visual Studio 的 Python 开发插件 PTVS

    PTVS (Python Tools for Visual Studio) http://pytools.codeplex.com/ 当前版本:2.1 RC PTVS (Python Tools fo ...

  9. 护肤品总结 Skin Care (2)

    接护肤品总结(1) 面膜篇 个人不太喜欢片状面膜,所以用膏状面膜比较多. 1. Origins Drink Up-Intensive Overnight Mask 悦木之源补水睡眠面膜 牛油果油油的质 ...

  10. DPDK2.1开发者手册4-7

    Mempool Labrary 一个内存池(memory pool)就是固定大小对象的分配器.在dpdk中,它是通过名字来标示唯一性的,且使用环形队列来保存没有使用的空闲对象.它提供了一些可选项服务例 ...