1.实现协议
- 正式协议是一个命名的方法列表(与非正式协议一样)
- 正式协议显式的要求采取协议(与非正式协议步一样)
- 采取协议的办法是在@interface声明中列出协议的名称;
- 采取协议意味着承诺实现协议的所有方法(正式协议与java的接口一样)
(一)声明协议:
@protocol NSCopying
-(id)copyWithZone:(NSZone *)zone;
@end
@protocol NSCoding
-(void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;
@end
理解:
@protocol 告诉编译器:下面将是一个新的正式协议。
@protocol 之后是协议名称,协议名称唯一
然后是方法声明列表,协议的每个采用者都必须实现这些方法。
@end 结束符
使用协议步引入新的实例变量。
(二)采用协议
@interface Car : NSObject<NSCoding,NSCopying>
{
//实例变量
}
//方法
@end
采用某个协议,在类的声明中列出该协议的名称,并用 < > 将协议名称括起来。
多个协议只见用逗号隔开,顺序步影响。
(三)实现协议
采用该协议的类的实现文件中,实现协议的声明的 v方法。
1).可以使用一下方法来检查一个对象是否遵守某个协议
if(![receiver conformsToProtocol:@protocol(MyXMLSupport)])
2).如果定义了自己的协议,并不意味着自己去实现它,但告诉其他程序员,如果要使用这项协议,则必须实现这些方法。
3).协议中的方法可从超累中继承,但并不意味着对于该子类,这些方法得到了正确的实现。当子类新增数据成员时???
2.常用协议
@protocol NSCopying
@protocol NSCoding
把对象编码为数据块,并保存在磁盘中。能将数据块读回到内存中。还能机遇保存的数据创建新的对象。
3.NSCopying协议
实质:
实现一个无实例变量类的复制,
即实现copy协议中的copyWithZone方法;
里程1:Engine类的复制
@interface Engine : NSObject<NSCopying>
{
//实例变量
}
//方法
@end
因为用了NSCopying协议,必须实现它的方法。
@implementation Engine
-(id)copyWithZone:(NSZone *)zone
{
Engine *engineCopy;
engineCopy = [[[self class]allocWithZone:zone]init];
/**
实现过程:
step1:[self class] 获取self对象所属的类。//向获取类就要发送class方法
step2:[[self class]allocWithZone:zone] 向该类发allocWithZone:zone消息,以分配内存并创建该类的一个新对象。//allocWithZone:zone使一个类消息
step3: 向心对象发送init消息,以使其初始化。 **/ return engineCopy;}@end
engineCopy = [[Engine allocWithZone:zone]init];
在子类继承的时候会出错。
4.深拷贝和浅拷贝
浅层复制 (shallow copy)不复制引用对象,新复制的对象只指向现有的引用对象。
深层复制(deep copy)将复制所有引用的对象。
1).遵守NSCopying协议的类才可以发送copy消息;
2).遵守NSMutableCopying协议的类才可以发送mutablecopy消息
3).一个类没有遵守上述两个协议,而发送copy,mutablecopy,会发生异常。
里程2:Tire类的复制
//有实例变量,切其子类又新添加实例变量的类的复制
@interface Tire : NSObject<NSCopying> {
float pressure;
float threadDepth;
}
@property float pressure;
@property float threadDepth;
-(id)initWithPressure:(float)pressure;
-(id)initWiththreadDepth:(float)threadDepth;
-(id)initWithPressure:(float)pressure WiththreadDepth:(float)threadDepth;
@end
实现文件:
@implementation Tire
-(id)copyWithZone:(NSZone *)zone
{
Tire *tireCopy;
tireCopy = [[[self class]allocWithZone:zone]initWithPressure:20.0f WiththreadDepth:20.0f];
/**
实现过程:
step1:[self class] 获取self对象所属的类。
step2:[[self class]allocWithZone:zone] 向该类发allocWithZone:zone消息,以分配内存并创建该类的一个新对象。
step3:
向心对象发送initWithPressure: WiththreadDepth:消息,以使其初始化。也可以使用见大init。
**/
return tireCopy;
}
@end
zone 来自方法参数,pressure和threaddepth 来自与类的成员变量。
里程4:
allweather的复制
@interface allWeathRadical : Tire {
float rain;
float snow;
}
@property float rain;
@property float snow;
@end
@implementation allWeathRadical
-(id)copyWithZone:(NSZone *)zone
{
allWeathRadical *tireCopy;
tireCopy = [super copyWithZone:zone];
[tireCopy setRain:rain];
[tireCopy setSnow:snow];
/**
step1:tireCopy = [super copyWithZone:zone];
调用超累的copyWithZone:zone方法
step2:
[tireCopy setRain:rain];
[tireCopy setSnow:snow];
调用访问器方法处理新增的实例变量
step3:
若子类无新增的实例变量,则可直接使用超类的协议方法,若新增,则需重写初始化方法。
**/
return tireCopy;
}
里程4.
实现car类的复制
实质:数据成员是指向oc对象的指针,调用协议方法,copy操作后内存管理方法。
在默认情况下,NSObject没有遵守这两个协议,但copy,mutable copy方法是nsobject定义的。
若要自定义copy,必须遵守nscopying协议,并实现copywithzone:方法
mutablecopy同上
遵守nscopying协议的基本是基础核心类,如nsstring,nsnumber;
copy后,返回一个新对象,程序员要负责释放,原先被拷贝对象的retaincount +1,所以不需要释放。
copy后,返回的是不能修改的对象,mutable copy返回的对象可能是可以修改的。
copy复制一个步可变对象。而mutable copy复制一个可变对象。
代码实例1:对非容器类对象的拷贝
1)。对一个不可变对象的复制,copy是指针复制,即浅拷贝;mutablecopy则是对象复制,即深拷贝。(实例1)
2)。对可变对象复制,都是深拷贝,但copy复制返回的对象是不可变的。(实例2)
代码实例2:对容器类本身
上面的结论也适用。
对容器而言,其元素对象事中是指针复制。如要元素对象的为对象复制,就需要实现深拷贝。
理解协议三步骤:声明协议/实现协议/使用协议
了解常用协议
理解深复制,浅复制
利用nscopying协议实现自定义objc对象的深复制。
了解nscopying协议对基础核心类对象的深/浅复制。