1、OC是在C语言基础上进行扩展得到的一门面向对象的程序设计语言,它也提供了定义类、成员变量和方法的基本功能。类可以被认为是一种自定义的数据类型,使用它可以定义变量,所有使用类定义的变量都是指针类型的变量,他们将会指向该类的对象。类用于描述客观世界中某一类对象的共同特征,而对象则是类的具体存在。
2、类的定义:OC中定义类分为两个步骤,接口部分和实现部分。OC学习篇之---类的定义
接口部分:定义该类包含的成员变量和方法
实现部分:为该类的方法提供实现
3、接口定义用@interface关键字,用@end表明定义结束,其中紧跟该类的一队花括号用于声明该类的成员变量,花括号后面的部分用于声明该类的方法。一般接口部分的定义格式和实现为:
@interface 类名:父类{
//定义属性,只定义,不赋值
属性类型 属性名;
}
//定义方法,只定义,不实现
-/+方法类型标识符 (返回值类型) 方法名:形参名 形参标签2:形参2;
@end
1 @interface Person : NSObject{
2 //在{}中定义属性(全局变量/实例变量)
3 //注意:只能定义不能赋值,因为这里只是在做声明操作,不能赋值的
4 //加上下划线,为了区分局部变量
5 NSString *_name;//姓名,默认值是nil:空指针,可以查看定义:#define nil NULL
6 NSInteger _age;//年龄,默认值是0
7 }
8
9 //定义方法
10 //-:实例方法,+:类方法
11 //格式:方法说明 (返回类型) 方法名 : (参数类型)参数名称
12 //注意方法名是shopping:,不是shopping,这个要注意
13 - (void)shopping:(float)price;
14
15 //定义方法设置属性值(注意setXXX)
16 - (void)setName:(NSString *)name;
17 - (void)setAge:(NSInteger)age;
18
19 //定义方法的获取属性值(注意不是getXXX,而是直接的属性名,因为getXXX在OC中还有其他用途),没有形参则可以省略冒号
20 - (NSString *)name;
21 - (NSInteger)age;
22
23 //多个参数的方法定义
24 //方法名两部分组成的:setName: setAge:
25 - (void)setName:(NSString *)name setAge:(NSInteger)age;
26 //或者方法名:setName: :,后面的可以省略,但是这种方式不建议使用
27 //- (void)setName:(NSString *)name :(NSInteger)age;
28
29 //类方法
30 //在这个方法中是无法访问属性的,因为属性是属于对象的,不是类的
31 + (Person *)newPerson;
32 @end
4、类的实现部分:接口部分只是对类的成员变量和方法进行声明,并没有为方法提供实现的方法体。类的实现用@implementation关键字进行标识,用@end表示结束。上述Person类的接口定义对应的实现如下。
1 @implementation Person
2
3 //实现方法
4 - (void) shopping : (float)price{
5 NSLog(@"%@ shopping %f",_name,price);
6 }
7
8 - (void)setName:(NSString *)name{
9 _name = name;
10 }
11 - (void)setAge:(NSInteger)age{
12 _age = age;
13 }
14 - (NSString *)name{
15 return _name;
16 }
17 - (NSInteger)age{
18 return _age;
19 }
20 - (void)setName:(NSString *)name setAge:(NSInteger)age{
21 _name = name;
22 _age = age;
23 }
24 + (Person *)newPerson{
25 return [[Person alloc] init];
26 }
27
28 @end
5、根据习惯,接口部分和实现部分分别使用两个源文件进行保存,通常接口部分在.h文件中对类进行定义和声明,而实现部分则在.m文件中进行实现,这样可以更好地实现面向对象的封装特性,只需要向外暴露接口部分以供调用,实现部分则属于该类的内部实现,对于外界而言是隐藏的。
6、对象的产生和使用:当一个对象被创建成功之后,这个对象将保存在堆内存中,OC不允许直接访问堆内存中的对象,只能通过该对象的指针变量来访问该对象。如果堆内存中的对象没有任何变量指向该对象,那么程序将无法再访问该对象,OC没有提供自动的垃圾回收机制,需要程序员自己释放该对象所占用的内存,否则就会造成内存泄漏。
1 //类的定义放在.h文件中
2 //类的实现放在.m文件中
6
7 #import <Foundation/Foundation.h>
9 #import "Person.h"
10
11 int main(int argc, const charchar * argv[]) {
12 @autoreleasepool {
13 //创建对象
14 //在内存中申请一块内存区域
15 //Person *person = [Person alloc];
16 //调用初始化方法,初始化一些默认数据
17 //可能上面申请的内存之前有被使用过,还会有以前的数据。所以我们需要将其数据清空,这时候就会将默认值进行赋值(相当于清空操作)
18 //person = [person init];
19
20 //合并
21 //这里申请了两块内存:一个是对象指针变量person,一个是alloc申请的保存Person对象的内存
22 //可以看出alloc/init方法是类方法、可以查看NSObject对象的定义,alloc相当于给这个对象分配内存空间,init是调用这个类的构造方法,对属性和字段进行初始化操作
23 Person *person = [[Person alloc] init];
24
25 //还有另外的一种方式创建一个对象,但是这种方式不建议使用,因为这种方式相当于把上面的两个合并
26 //有时候我们需要将上面的两个步骤进行分开操作的
27 //Person *person1 = [Person new];
28
29 //设置名字
30 [person setName:@"jaingwei"];
31
32 //调用实例方法shopping
33 [person shopping:200];
34
35 Person *person1 = [[Person alloc] init];
36 [person1 setName:@"huangdaoyang"];
37 [person1 shopping:300];
38 //同时设置两个属性的值,但是这种方式不建议使用,建议使用set方法
39 [person1 setName:@"huangdaoyang" setAge:22];
40
41 //get方法调用
42 NSString *person_name = [person name];
43 NSLog(@"name is %@",person_name);
44 NSString *person1_name = [person1 name];
45 NSLog(@"name is %@",person1_name);
46
47 //类方法调用
48 Person *person2 = [Person newPerson];
49 [person2 setName:@"shixin" setAge:22];
50 [person2 shopping:400];
51
52 //空指针
53 Person *person3 = nil;
54 //不执行任何操作,但是也不会报错空指针异常
55 [person3 setName:@"空对象" setAge:22];
58 }
59 return 0;
60 }
7、 类的初始化方法init相当于Java中的构造方法,但是OC中没有默认的init方法,必须自己实现。此外,我们还可以进行自定义初始化方法,对对象的成员变量进行初始化赋值,但是自定义的初始化方法必须以init开头命名。具体的接口分布和实现部分的示例代码如下:
1 @interface Person : NSObject{
2 NSString *_name;
3 NSInteger _age;
4 }
5
6 //自定义初始化方法,必须以init开头
7 - (id)initWithName:(NSString *)name withAge:(NSInteger)age;
8
9 //打印信息
10 - (void)showInfo;
11
12 @end
1 @implementation Person
2
3 - (id)initWithName:(NSString *)name withAge:(NSInteger)age{
4 //固定写法,可以背下来哦~~
5 //调用父类的初始化方法
6 self = [super init];
7
8 if(self != nil){
9 _name = name;
10 _age = age;
11 }
12
13 return self;
14 }
15
16 - (void)test{
17 NSLog(@"test");
18 }
19
20 - (void)showInfo{
21 [self test];//调用自己的方法
22 NSLog(@"name is %@ and age is %d",_name,_age);
23 }
24
25 @end
8、OC中方法的所属性主要体现在如下几个方面:
9、在方法定义时我们有时候需要允许方法根据需要传递不确定个数的参数,即形参个数可变的方法在OC中是可以实现的,类似OC中的NSLog()函数就可以传入任意多个参数。如果在定义方法时,在最后一个形参名之后曾加都好和三点(,...),则表明该形参可以接受多个参数值。
为了在程序中获取多个可变的形参,需要使用到如下关键字:
1 #import <Foundation/Foundation.h>
2
3 @interface VarArgs:NSObject
4 //不定义成员变量,直接定义可变参数的方法
5 - (void) test : (NSString *) name, ...;
6 @end
7
8 @implementation VarArgs
9 - (void) test : (NSString *) name, ...
10 {
11 //使用va_list定义一个argList变量,该指针指向可变参数列表
12 va_list argList ;
13 //如果第一个name存在才需要处理后面的参数
14 if(name)
15 {
16 //由于name参数并不在列表里,因此先处理name参数
17 NSLog(@"%@", name) ;
18 //使用va_start方法让argList指向参数列表的第一个元素
19 va_start(argList,name) ;
20 //使用va_arg依次提取argList中的参数
21 NSString * str ;
22 while(str = va_arg(argList,id))
23 {
24 NSLog(@"%@", str) ;
25 }
26 //释放argList指针,结束提取
27 va_end(argList) ;
28 }
29 }
30 @end
31
32 int main(int argc, char * argv[])
33 {
34 VarArgs * va = [[VarArgs alloc] init] ;
35 [va test:@"疯狂IOS讲义", @"疯狂iosj讲义", @"i love ios", nil] ;
36 }