小常识:可以在使用的数据类型中为实例变量和方法指定协议名称。这样,可以给Objective-C的编译器提供更多的信息,从而有助于检查代码中的错误。
-(void)setObjectValue:(id<NSCopying>)obj ;
编译器知道,你期望任意类型的对象,只要其遵守该协议。
@protocol NSCopying
-(void)copyWithZone:(NSZone*)zone;
@end
@protocol NSCoding
-(void)encodeWithCoder:(NSCoder*)acoder;
-(id)initWithCoder:(NSCoder*)aDecoder;
@end
@Class Tire;
@Class Engine;
@interface Car:NSObject<NSCopying,NSCoder>
{
NSString *name;
NSMutableArray *tires;
Engine *engine;
}
-(void)setTire:(Tire*)tire atIndex:(int)index;
-(Tire*)tireAtIndex:(int)index;
-(void)print;
@property(copy)NSString *name;
@property(retain)Engine *engine;
@end
@implementation Car
-(id)copyWithZone:(NSZone*)zone
{
Car *carCopy;
carCopy=[[[self class] allocWithZone:zone]
init];
carCopy.name=self.name;
//name属性复制其字符串对象
Engine *engineCopy;
engineCopy=[[engine copy]autorelease];
carCopy.engine=engineCopy;
/*或者
engineCopy=[engine copy]; retainCount +1
carCopy.engine=engineCopy; retainCount +1
[engineCopy release]; */ retainCount -1
int i;
for(i=0;i<4;i++)
{
Tire *tireCopy;
tireCopy=[[self tireAtIndex:i]copy];
[tireCopy autorease];
[carCopy setTire:tireCopy
atIndex:i];
}
return carCopy;
}
-(id)init
{
if(self=[super init])
{
tires=[[NSMutableArray alloc]init];
int i;
for(i=0;i<4;i++)
{
[tires addObject:[NSNull null]];
}
}
return self;
}
-(void)setTire:(Tire*)tire atIndex:(int)index
{
[tires replaeObjectAtIndex:index withObject:tire];
}
-(tire*)tireAtIndex:(int)index
{
Tire *tire;
tire=[tires objectAtindex:index];
return tire;
}
-(void)dealloc
{
[tires release];
[engine release];
[super dealloc];
}
-(void)print
{
int i;
for(i=0;i<4;i++)
{
NSLog(@"%@",[self tireAtIndex i]);
}
NSLog(@"%@",engine);
}
@interface:Tire:NSObject<NSCopying>
{
float pressure;
float treadDepth;
}
-(id)initWithPressure:(float)pressure;
-(id)initWithTreadDepth:(float)treadDepth;
-(id)initWithPressure:(float)pressure TreadDepth:(float)treadDepth;
//指定初始化函数(designating initializer)
@property float pressure;
@property float treadDepth;
@end
@implementation:Tire
@synthesize pressure;
@synthesize treadDepth;
-(id)copyWithZone:(NSZone*)zone
{
id tireCopy;
/* 虽然这样写没错,但是破坏了封装原则,父类改变了子类的选择
if([[self class] is memberOfClass [Tire class]])
{
tireCopy=[[Tire allocWithZone:zone]
initWithPressure:pressure
treadDepth:treadDepth];
}
else
{
tireCopy=[[[self class]allocWithZone:zone]
initWithPressure:pressure TreadDepth:treadDepth
rainHanding:rainHanding
snowHanding:snowHanding];
[self class ]这里代表Tire的子类,调用子类初始化方法
}
*/
tireCopy=[[[self class] allocWithZone:zone]
initWithPressure:pressure
treadDepth:treadDepth];
return tireCopy;
}
-(id)initWithPressure:(float)p TreadDepth:(float)td
{
//此方法为 指定初始化函数(designated initializer) Tire类的所有
初始化方法使用此函数执行初始化操作。子类使用其超类的 指定初始化函数
实现超类初始化(通常接受参数最多的初始化方法最终成为 指定初始化函数)
if(self=[super init]) //调用父类init方法,很重要,确保超类获得对象并使其运行;
{
pressure=p;
treadDepth=td;
}
}
-(id)init
{
if(self=[self initWithPressure:(float)34
TreadDepth:(float)20]){
}
return self;
}
-(id)initWithPressure:(float)pressure
{
if(self=[self initWithPressure:(float)pressure
TreadDepth:(float)20]){
}
return self;
}
-(id)initWithTreadDepth:(float)treadDepth
{
if(self=[self initWithPressure:(float)34
TreadDepth:(float)treadDepth]){
}
return self;
}
... ...
@interface AllWeatherRadia:Tire 因AllWeatherRadia是Tire子类
已经获得了Tire的所有属性,包括对协议的遵守
所以不需要<NSCopying>
{
float rainHanding;
float snowHanding;
}
-(id)initWithPressure:(float)p TreadDepth:(float)td
@property float rainHanding;
@property float snowHanding;
@end
@implementation AllWeatherRadia
@synthesize rainHanding;
@synthesize snowHanding;
-(id)copyWithZone:(NSZone*)zone
{
AllWeatherRadia *awr;
awr=[super copyWithZone:zone];
awr.rainHanding=self.rainHanding;
awr.snowHanding=self.snowHanding;
return awr;
-(id)initWithPressure:(float)p TreadDepth:(float)td
{
if(self=[self initWithPressure:(float)p TreadDepth:(float)td
rainHanding:(float)23.7f
snowHanding:(float)42.5f])
{
}
return self;
}
-(id)initWithPressure:(float)p TreadDepth:(float)td
rainHanding:(float)rh
snowHanding:(float)sh
{
if(self=[super initWithPressure:(float)p TreadDepth:(float)td])
{
rainHanding=rh;
snowHanding=sh;
}
return self;
}