03OC的类的补充
上一章我们介绍了类的定义,以及类的里面如何定义成员变量,如何定义方法等等。
一、self关键字
1.在C#中有关键字this表示当前对象,其实在OC中也有类似的关键字self,只是self关键字不仅表示当前对象还可以表示类本身,也就是说它既可以放在静态方法,又可以用在动态方法。
#import "Person.h" @implementation Person -(void)setName:(NSString *)name andAge:(int)age{ // _name=name; // _age=age; self.name=name; self.age=age; } +(void)printInfo{ NSLog(@"Hello,World!"); } +(void)showMessage{ [self printInfo]; } @end
然后看看调用的时候:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { Person *p=[[Person alloc]init]; [p setName:@"Kenshin" andAge:28]; [Person showMessage]; return 0; }
其中,setNameandAge是一个动态方法,这个时候self表示p这个对象,而showMessage代表的是调用的类,因此self为当前方法的调用者。
关于self的注意点:
#import "Person.h" @implementation Person -(void)setName:(NSString *)name{ self.name=name; }
这是一段实现属性的代码,self.name=name;其实就是调用self.setName=name;这样就会造成死循环。所以在没有用到@property自动生成的属性的时候,在定义成员变量的时候,都加上下划线。(_name好习惯)
二、构造函数
前面我们创建类的对象,在初始化的时候需要调用init方法(构造函数),下面我们看一喜爱自定义构造函数
实现代码:
//自定义构造方法 -(id)initWithName:(NSString *)name andAge:(int)age{ if(self=[super init]){ //super代表父类 self.name=name; self.age=age; } return self; }
OC中super代表父类,通过调用父类的方法给当前对象赋值,然后判断这个对象是否为nil,如果不为空则依次给name、age属性赋值。
看看如何调用:
int main(int argc, const char * argv[]) {
Person *p=[[Person alloc]initWithName:@"Kenshin" andAge:28]; NSLog(@"name=%@,age=%i",p.name,p.age); //结果:name=Kenshin,age=28 return 0; }
通过自定义构造方法固然可以简化代码,但是在使用时还要手动申请内存,在OC中一般我们通过定义一个静态方法来解决这个问题
//通过静态方法获得一个对象 +(id)personWithName:(NSString *)name andAge:(int)age{ Person *p=[[Person alloc]initWithName:name andAge:age]; return p; }
int main(int argc, const char * argv[]) { Person *p=[[Person alloc]initWithName:@"Kenshin" andAge:28]; NSLog(@"name=%@,age=%i",p.name,p.age); //结果:name=Kenshin,age=28 Person *p2=[Person personWithName:@"Kaoru" andAge:27]; NSLog(@"name=%@,age=%i",p2.name,p2.age); //结果:name=Kaoru,age=27 return 0; }
三、description方法
在C#每个类都有一个ToString()方法用于打印一个对象的信息、在OC中这个方法叫description,例如前面的Person类我们可以重写这个方法用于打印调试:
@implementation Person -(NSString *)description{ return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age]; }
int main(int argc, const char * argv[]) { Person *p=[[Person alloc]init]; p.name=@"Kenshin"; p.age=28; NSLog(@"%@",p);//此时会调用对象description方法返回对应的描述信息 /*结果: name:Kenshin,age:28} */ return 0; }
注意看NSLog的格式符为%@,当使用%@输出一个对象的时候,OC就会调用这个对象的description进行输出,默认情况下,我们不重写description方法时,输出内容应该为<类名:地址>例如:“<Person: 0x100202310>”千万不要在descripton中打印输出self,因为输出self的时候会调用该对象的descripton方法,这样一来就造成死循环。
四、继承
由于OC是面向对象语言,当然支持继承,其实我们的Persion已经继承了NSObject。子类可以重写父类的方法和属性。不详细说。