昨天介绍了OC中类的定义和使用,今天我们来继续学习类的初始化方法和点语法的使用。
一、首先来看一下类的初始化方法
在Java中我们知道一个每个类都有构造方法,这里的初始化方法就是和构造方法一个概念的,但是这里有一个区别是:Java中有默认构造方法,当我们去自定义构造方法的时候,这个默认构造方法就会被替换了,但是OC中是不会的,这点需要注意。
下面来看一下如何自定义初始化方法:
Person.h
1 // 2 // Person.h 3 // 03_InitDemo 4 // 5 // Created by jiangwei on 14-10-10. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface Person : NSObject{ 12 NSString *_name; 13 NSInteger _age; 14 } 15 16 //自定义初始化方法,必须以init开头 17 - (id)initWithName:(NSString *)name withAge:(NSInteger)age; 18 19 //打印信息 20 - (void)showInfo; 21 22 @end
这里我们定义了一个初始化方法,对名称和年龄进行初始化赋值操作
注:OC中自定义初始化方法的名称必须是以init开头
在来看一下实现:
Person.m
1 // 2 // Person.m 3 // 03_InitDemo 4 // 5 // Created by jiangwei on 14-10-10. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import "Person.h" 10 11 @implementation Person 12 13 - (id)initWithName:(NSString *)name withAge:(NSInteger)age{ 14 //固定写法,可以背下来哦~~ 15 16 //调用父类的初始化方法 17 self = [super init]; 18 19 if(self != nil){ 20 _name = name; 21 _age = age; 22 } 23 24 return self; 25 } 26 27 - (void)test{ 28 NSLog(@"test"); 29 } 30 31 - (void)showInfo{ 32 [self test];//调用自己的方法 33 NSLog(@"name is %@ and age is %d",_name,_age); 34 } 35 36 @end
这里我们看到了,初始化方法返回的类型是id类型,关于OC中的id类型,可以认为和C语言中的void*是相等的,这种类型在OC中经常被用到,还有就是self关键字的使用,这里的self关键字就相当于Java中的this关键字,指代当前类对象,还有super关键字,这个和Java中的super也是一样的,指代父类对象。还有一个是nil,他就相当于Java中的null,空对象的概念,用于判断的。
同时这里还要记住一点:
以后OC中自定义初始化的方法的模板:
1 //固定写法,可以背下来哦~~ 2 //调用父类的初始化方法 3 self = [super init]; 4 if(self != nil){ 5 _name = name; 6 _age = age; 7 } 8 return self;
这个没什么好说的,就是一个模板,所以初学者就背下来吧,不过用多了,自然就记住了。
下面来看一下如何使用初始化方法:
main.m
1 // 2 // main.m 3 // 03_InitDemo 4 // 5 // Created by jiangwei on 14-10-10. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 #import "Person.h" 12 13 int main(int argc, const charchar * argv[]) { 14 @autoreleasepool { 15 //初始化方法只能调用一次 16 Person *person = [[Person alloc] initWithName:@"jiangwei" withAge:22]; 17 [person showInfo]; 18 19 person = [[Person alloc] init]; 20 [person showInfo]; 21 22 //id类型,类似于void* 23 //但是id类型一般不这么使用,一般会作为方法的返回值和传入的参数类型 24 id person1 = [[Person alloc] initWithName:@"huangdaoyang" withAge:23]; 25 [person1 showInfo]; 26 } 27 return 0; 28 }
我们使用了我们自定义的方法实例化了一个Person对象出来,同时调用他的showInfo方法,打印结果,这里我们也会发现Person的init方法任然可以使用,这个和Java中是有区别的,其实,在上篇文章中说到过,这个init方法是NSObject父类的,可以猜想到这个方法的逻辑功能就是初始化,所以我们在自定义初始化方法的时候,都是会用到这个方法的。当然我们可以定义多个初始化方法,后面我们在介绍Foundation框架的时候,会发现系统给我提供的类有很多自定义的初始化方法。
运行结果:
二、看一下OC中的点语法
OC中的点语法其实没什么高端的,但是他和Java中的那种使用对象变量直接访问public类型的变量的点是不一样的,所以这里就单独说明一下:
点语法只能适用于set/get方法,如果没有对应的set/get方法的话,是不能使用.语法的
OC中的get方法和Java中不太一样,OC中只要一个方法有返回值都可以认为是get方法,Java中是形如getXXX这样的才叫做get方法。
下面来看一个例子吧:
Person.h
1 // 2 // Person.h 3 // 04_UseDit 4 // 5 // Created by jiangwei on 14-10-11. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface Person : NSObject{ 12 //点语法只能适用于set/get方法,如果没有对应的set/get方法的话,是不能使用.语法的 13 //这里的get方法和其他语言不一样,只要有返回值就是get方法 14 NSString *_name; 15 NSInteger _age; 16 } 17 18 - (void)setName:(NSString *)name; 19 - (void)setAge:(NSInteger)age; 20 21 - (NSString *)name; 22 - (NSInteger) age; 23 24 //这里要注意,showInfo也是一个get方法 25 - (NSString *)showInfo; 26 27 //只定义,不实现,所以在调用[person test]的时候,编译时候不会报错 28 //但是运行的时候就会报错了,因为编译的时候只会判断方法有没有定义,而运行的时候是需要判断这个方法有没有实现 29 - (void)test; 30 31 @end
在{}中定义了两个属性,注意都是以下划线开头的。然后在给这两个属性定义get/set方法,这样我们就可以使用点语法来访问这两个属性了。
同时这里要注意的是其实showInfo方法也是一个get方法,因为他又一个返回值类型。
所以在OC中使用点语法有两个条件:
1、必须是属性
2、有对应的get/set方法
下面来看一下实现吧:
Person.m
1 // 2 // Person.m 3 // 04_UseDit 4 // 5 // Created by jiangwei on 14-10-11. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import "Person.h" 10 11 /** 12 #import和#include的区别 13 1.当我们在代码中使用两次#include的时候会报错:因为#include相当于拷贝头文件中的声明内容,所以会报重复定义的错误 14 但是使用两次#import的话,不会报错,所以他可以解决重复导入的问题,他会做一次判断,如果已经导入一次就不导入了 15 */ 16 17 @implementation Person 18 19 - (void)setName:(NSString *)name{ 20 _name = name; 21 NSLog(@"setName is Execute"); 22 } 23 - (void)setAge:(NSInteger)age{ 24 //这里要注意,如果我们定义的全局变量是age而不是_age的话 25 //这里不能用age = age进行赋值 26 //但是也不能使用self.age = age,因为self.age等价于[self setAge:age]这样就会出现死循环了 27 //所以我们在定义全局变量的时候一般都会加上一个下划线以便区分 28 _age = age; 29 NSLog(@"setAge is Execute"); 30 } 31 - (NSString *)name{ 32 NSLog(@"getName is Execute"); 33 return _name; 34 } 35 - (NSInteger) age{ 36 NSLog(@"getAge is Execute"); 37 return _age; 38 } 39 - (NSString *)showInfo{ 40 NSLog(@"showInfo is Execute"); 41 return _name; 42 } 43 44 @end
我们看到了这里对get/set方法的实现,看到上面的注释:
我们这里不能使用self.age = age,因为self.age等价于[self setAge:age],这样就会出现死循环了
这个和Java就有很大的区别了,Java中我们是可以使用this.age = age的,而且经常这样做,但是OC中不行,原因很简单,因为OC中的点语法相当于调用set/get方法,那么在set/get方法中调用set/get方法,那就会出现了死循环了。所以这点一定要注意。
还有一个需要注意的是,刚刚在Person.h中定义了一个test方法,但是在Person.m中并没有实现,在OC中编译是不会报错的,但是运行的时候就会报错了。
看一下如何使用点语法:
main.m
1 // 2 // main.m 3 // 04_UseDit 4 // 5 // Created by jiangwei on 14-10-11. 6 // Copyright (c) 2014年 jiangwei. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 #import "Person.h" 12 13 int main(int argc, const charchar * argv[]) { 14 @autoreleasepool { 15 Person *person = [[Person alloc] init]; 16 //此处的点语法调用的是set方法,等价于[person setName:@"jiangwei"]; 17 person.name = @"jiangwei"; 18 person.age = 22; 19 //此处的点语法调用的get方法,等价于NSString *name = [person name]; 20 NSString *name = person.name; 21 NSLog(@"name is %@",name); 22 23 name = person.showInfo; 24 NSLog(@"name is %@",name); 25 26 //调用test方法 27 [person test]; 28 } 29 return 0; 30 }
我们这里就可以使用点语法进行赋值和取值操作了,其实等价于调用他们的get/set方法。
运行结果:
这里需要注意的是报了一个错误,这个错误也是我们后面开发过程中经常犯的一个错误,就是这个方法没有实现,我们在Person.h中定义了test方法,但是没有在Person.m中进行实现,在main.m中进行调用就报了这个错误,但是编译的时候是没有报错的。
总结
今天就简单的介绍了OC中的初始化方法的定义和点语法的使用,其中初始化方法类似于Java中的构造方法,点语法就是get/set的缩减版