我们知道写oc代码时可能会创建很多的类和对象,我们要修改对象的值时就使用oc的setter方法(设置属性值)和getter方法(读取属性值),代码量会很大,这就增加了写代码的时间。先来看看使用存取方法的一小段程序:
#import <Foundation/Foundation.h>
@interface Tire : NSObject
@end
@implementation Tire
-(NSString *)description
{
return (@"I am a tire.I last a while");
}
@end
@interface Engine : NSObject
@end
@implementation Engine
-(NSString *)description
{
return (@"I am an engine.Vrooom!");
}
@end
@interface Car : NSObject
{
Engine *engine;
Tire *tires[4];
}
//Engine类的getter方法
-(Engine *)engine;
//Engine类的setter方法
-(void)setEngine:(Engine *)newEngine;
//Tire类的getter方法
-(Tire *)tireAtIndex:(int)index;
//Tire类的setter方法
-(void)setTire:(Tire *)tire atIndex:(int)index;
-(void)print;
@end
@implementation Car
-(Engine *)engine
{
return (engine);
}
-(void)setEngine:(Engine *)newEngine
{
engine = newEngine;
}
-(Tire *)tireAtIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in tireAtIndex:",index);
exit(1);
}
return (tires[index]);
}
-(void)setTire:(Tire *)tire atIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in setTire:atIndex:",index);
exit(1);
}
tires[index] = tire;
}
-(void)print
{
NSLog(@"%@",engine);
NSLog(@"%@",tires[0]);
NSLog(@"%@",tires[1]);
NSLog(@"%@",tires[2]);
NSLog(@"%@",tires[3]);
}
@end
int main(int argc, const char * argv[]) {
Car *car = [Car new];
Engine *engine = [Engine new];
[car setEngine:engine];
for(int i = 0;i < 4;i++)
{
Tire *tire = [Tire new];
[car setTire:tire atIndex:i];
}
[car print];
return 0;
}
还好我们还可以简化这些代码,在接口声明中我们使用@property关键字,在实现中我们使用@synthesize关键字。代码如下:
#import <Foundation/Foundation.h>
@interface Tire : NSObject
@end
@implementation Tire
-(NSString *)description
{
return (@"I am a tire.I last a while");
}
@end
@interface Engine : NSObject
@end
@implementation Engine
-(NSString *)description
{
return (@"I am an engine.Vrooom!");
}
@end
@interface Car : NSObject
{
Engine *engine;
Tire *tires[4];
}
@property Engine *engine;
//Tire类的getter方法
-(Tire *)tireAtIndex:(int)index;
//Tire类的setter方法
-(void)setTire:(Tire *)tire atIndex:(int)index;
-(void)print;
@end
@implementation Car
@synthesize engine;
-(Tire *)tireAtIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in tireAtIndex:",index);
exit(1);
}
return (tires[index]);
}
-(void)setTire:(Tire *)tire atIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in setTire:atIndex:",index);
exit(1);
}
tires[index] = tire;
}
-(void)print
{
NSLog(@"%@",engine);
NSLog(@"%@",tires[0]);
NSLog(@"%@",tires[1]);
NSLog(@"%@",tires[2]);
NSLog(@"%@",tires[3]);
}
@end
int main(int argc, const char * argv[]) {
Car *car = [Car new];
//通过属性来设置Car对象里的成员,而不需要发送setter消息来设置(即不需要显示调用setter方法),而且这里我们使用了点运算符
car.engine = [Engine new];
for(int i = 0;i < 4;i++)
{
Tire *tire = [Tire new];
[car setTire:tire atIndex:i];
}
[car print];
return 0;
}
看上面的代码是不是简化了?@property是一种新的编译器功能,它意味着声明了一个新对象的属性。@property预编译指令的作用是自动声明属性的setter和getter方法,@synthesize也是一种新的编译器功能,它表示“创建了该属性的访问代码”。所有的属性都是基于变量的,所以你在合成setter和setter方法的时候,编译器会自动创建与属性名称相同的实例变量。假设你有一个子类,并且想要从子类直接通过属性来访问变量。在这种情况下,变量就必须放在头文件中。如果变量只属于当前类,则可以把它们放在.m文件里(并且要删除原interface代码中的声明语句)。还有,如果我们没有指定实例变量,编译器会自动帮我们创建。如下:
#import <Foundation/Foundation.h>
@interface Tire : NSObject
@end
@implementation Tire
-(NSString *)description
{
return (@"I am a tire.I last a while");
}
@end
@interface Engine : NSObject
@end
@implementation Engine
-(NSString *)description
{
return (@"I am an engine.Vrooom!");
}
@end
@interface Car : NSObject
{
//Engine *engine; //删除了声明的实例变量,但不会有任何影响
Tire *tires[4];
}
@property Engine *engine;
//Tire类的getter方法
-(Tire *)tireAtIndex:(int)index;
//Tire类的setter方法
-(void)setTire:(Tire *)tire atIndex:(int)index;
-(void)print;
@end
@implementation Car
@synthesize engine;
-(Tire *)tireAtIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in tireAtIndex:",index);
exit(1);
}
return (tires[index]);
}
-(void)setTire:(Tire *)tire atIndex:(int)index
{
if(index < 0 || index > 3)
{
NSLog(@"bad index (%d) in setTire:atIndex:",index);
exit(1);
}
tires[index] = tire;
}
-(void)print
{
NSLog(@"%@",engine);
NSLog(@"%@",tires[0]);
NSLog(@"%@",tires[1]);
NSLog(@"%@",tires[2]);
NSLog(@"%@",tires[3]);
}
@end
int main(int argc, const char * argv[]) {
Car *car = [Car new];
//通过属性来设置Car对象里的成员,而不需要发送setter消息来设置(即不需要显示调用setter方法),而且这里我们使用了点运算符
car.engine = [Engine new];
for(int i = 0;i < 4;i++)
{
Tire *tire = [Tire new];
[car setTire:tire atIndex:i];
}
[car print];
return 0;
}
以上代码中还巧妙的使用了点表达式,点表达式可以用来设置和访问对象的属性。上述几个程序运行的结果都一样,读者可以试着编译运行一下,博主编译后运行结果截图如下:
最后,谢谢各位读者的浏览。