Objective C 中的面向对象 Hello World Objective C Objective C中的数据类型 Objective C 中的面向对象 内容概述 对象、类简介 Objective C中类的定义 实例变量、实例方法、类方法 类的实例化及方法的调用 类的初始化 属性 1.1 对象和类的简介 任何面向对象的计算机语言都离不开讨论类和对象的感念,这也是初学者学习面向对象语言的一个屏障。有了对基本感念的理解,才能深入面向对象的精髓。 类是同一类型的抽象,例如:房子、汽车。有句话这样讲"物以类聚",类是一个静态概念,是一种自定义变量类型。类一般由属性、初始化方法和普通方法组成。 而对象是类的一个具体实现,例如我家的房子和我家的汽车就是房子和汽车类的对象。类和对象的关系是,类是对象的一个模板,而对象是类的一个实例。 1.2 Objective C中类的定义 Objective C中类的定义分为两个部分,声明部分和实现部分,并且一般分为两个文件,分别是.h文件和.m文件。下面是一个Person类的定义。 Person.h #import \<Foundation/Foundation.h\> @interface Person : NSObject @end Person.m #import "Person.h" @implementation Person @end 在上述代码的Person.h头文件中 #import \<Foundation/Foundation.h\>是导入头文件语句,因为这里使用的NSObject类在该头文件中,关键字@interface和@end 表示声明的开始和结尾,中间可以定义属性和方法。Person是类名称,:表示继承关系,这里继承NSObject。 Person.m 实现文件中,@implementation和@end是实现文件的开始和结尾,中间部分是方法的实现。 下面代码定义了一个Person类,有两个实例变量和一个方法。 #import \<Foundation/Foundation.h\> @interface Person : NSObject { int age; NSString \*name; } -(void)printMsg; @end #import "Person.h" @implementation Person -(void)printMsg{ NSLog(@"%@,%d",name,age); } @end 1.3 实例变量、实例方法、类方法 在类中定义的变量可以分为实例变量、类变量和局部变量。每个对象的实例变量都是不相同的,例如,我的姓名和你的姓名是不同。类变量是所有对象共享的。局部变量在方法中声明或者是函数的参数。 在类中定义的方法分为类方法和实例方法,类方法以"+"号开始,实例方法以"-"号打头。类方法无需实例化,通过类名称可以直接调用。实例方法必须实例化类才能调用。 下面代码定义了两个实例变量,并定义一个实例方法一个类方法。 Employee.h头文件 #import \<Foundation/Foundation.h\> @interface Employee : NSObject { // 实例变量员工编号 int eid; // 实例变量员工姓名 NSString \*name; } // 实例方法 -(void)instanceMethod; // 类方法 +(void)classMethod; @end Employee.m实现文件 #import "Employee.h" @implementation Employee -(void)instanceMethod{ NSLog(@"This is a instance method..."); } +(void)classMethod{ NSLog(@"This is a class method..."); } @end 测试文件main.m #import \<Foundation/Foundation.h\> #import "Employee.h" int main(int argc, const char \* argv[]) { @autoreleasepool { Employee \*emp = [[Employee alloc]init]; // 必须实例化才能调用 [emp instanceMethod]; // 通过类名称就可以调用 [Employee classMethod]; } return 0; } 1.4 类的实例化及方法的调用 类的实例化是由类创建对象的过程,由一个类可以创建若干个对象。实例化一个类可以使用NSObject的new关键字也可以使用NSObject的alloc和init,new方法实例化对象几乎很少用到,alloc表示分配内存区域,而init表示初始化,例如,给实例变量赋值。 关于Objective C中方法的调用和其它编程语言有所不同,Objective C中方法的调用使用[]语法格式。下面我们定义一个Student类,实例化两个学生,并调用他们的赋值和取值方法。 Student.h头文件声明 #import \<Foundation/Foundation.h\> @interface Student : NSObject { // 实例变量,学生编号 int sid; // 实例变量,学生姓名 NSString \*name; } // 赋值方法,传递int类型的参数mySid -(void)setSid:(int)mySid; // 取值方法,返回int类型的学生编号 -(int)sid; // 赋值方法,传递NSString类型的参数myName -(void)setName:(NSString\*)myName; // 取值方法,返回NSString类型的学生姓名 -(NSString\*)name; @end Student.m实现文件 #import "Student.h" @implementation Student // 实现姓名的赋值方法 -(void)setName:(NSString \*)myName{ name = myName; } // 实现姓名取值方法 -(NSString\*)name{ return name; } // 实现sid的赋值方法 -(void)setSid:(int)mySid{ sid = mySid; } // 实现sid的取值方法 -(int)sid{ return sid; } @end 方法的调用 // 实例化第一个学生 Student \*s1 = [[Student alloc]init]; // 调用赋值方法赋值 [s1 setSid:1]; [s1 setName:@"tom"]; // 调用取值方法取值 int sid1 = [s1 sid]; NSString \*name1 = [s1 name]; // 输出sid和name NSLog(@"%d,%@",sid1,name1); // 实例化第二个学生 Student \*s2 = [[Student alloc]init]; [s2 setSid:2]; [s2 setName:@"kite"]; NSLog(@"%d,%@",[s2 sid],[s2 name]); 多参数方法的定义和调用,和无参数和单参数方法的定义和调用有所不同。下面看一个例子。 // 多参数方法定义 -(void)setSid:(int)mySid andName:(NSString\*)myName; 这里setSid和andName组合形成方法名称,而mySid和myName是参数,:将方法名称和参数名称分隔开来,空格分隔多个不同参数。调用方法如下: // 多参数方法的调用 Student \*s3 = [[Student alloc]init]; [s3 setSid:3 andName:@"rose"]; 1.5 类的初始化 像其他面向对象语言,例如,c++、java都有构造方法,该方法一般在实例化对象时调用,作业是初始化实例化变量。Objective C也有对应的概念,那就是初始化init方法。 init方法是NSObject对象的方法,一般我们自己定义的类,都要通过覆盖该方法来实现对实例变量的初始化。下面我们定义一个客户类Customer,该类有三个实例变量分别是cid、name和email。我们通过覆盖init方法初始化这几个变量。 Customer.h代码 #import \<Foundation/Foundation.h\> @interface Customer : NSObject { // 实例变量cid、name和email int cid; NSString \*name; NSString \*email; } // 打印客户信息 -(void)printMsg; @end Customer.m 代码 @implementation Customer // 打印信息 -(void)printMsg{ NSLog(@"%d,%@,%@",cid,name,email); } // 初始化方法 -(id)init{ // 调用父类的初始化方法 self = [super init]; // 如果父类初始化成功 if (self) { // 初始化子类 cid = 1; name = @"tom"; email = @"tom@gmail.com"; } return self; } @end 这里我们覆盖init方法,该方法返回id类型。我们先调用父类的init方法,如果父类初始化成功,再来初始化子类。并且返回self(self代表当前对象)。 我们也可以定义带参数的初始化方法,在实例化时动态初始化对象。 // 多参数初始化方法的定义 -(id)initWithCid:(int)myCid andName:(NSString\*)myName andEmail:(NSString\*)myEmail; // 多参数初始化方法的实现 -(id)initWithCid:(int)myCid andName:(NSString \*)myName andEmail:(NSString \*)myEmail{ self = [super init]; if (self) { cid = myCid; name = myName; email = myEmail; } return self; } 初始化方法的调用 // 多参数初始化方法 Customer \*c = [[Customer alloc]initWithCid:1 andName:@"tom" andEmail:@"tom@gmail.com"]; [c printMsg]; 1.5 属性 当我们在类中定义了实例变量之后,我们经常需要定义针对这些实例变量的赋值和取值方法。这些方法的定义都是一致的,而且枯燥乏味。所有Objective C定义了@property标记来动态生产赋值和取值方法。而且可以使用@synthesize标记来生产赋值和取值方法的实现。下面代码我们定义了一个Teacher类,并定义了三个实例变量和三个属性,并通过@synthesize生产赋值和取值方法实现。 @interface Teacher : NSObject { // 实例变量 int tid; NSString \*name; int age; } // 属性,生产赋值和取值方法 @property(nonatomic)int tid; @property(nonatomic,strong)NSString \*name; @property(nonatomic)int age; @end #import "Teacher.h" @implementation Teacher // 生产赋值和取值方法 @synthesize tid; @synthesize name; @synthesize age; @end 我们看到在属性声明的()中有nonatomic和stong等关键字。这里nonatomic表示线程非安全的,strong表示强引用(这和内存管理有关,后续章节将详细讲述)。另外,括号中可以出现的关键字和表示的含义如下: assign:直接赋值 atomic:线程安全的 copy:赋值时拷贝对象 readonly:属性是只读的(没有set方法) readwrite:读写的(默认) retain:保留引用,引用计数+1 strong:强引用同retain weak:弱引用,应用在循环引用中 unsafe_unretained:非安全引用 另外,我们可以通过点操作法来访问属性,例如: Teacher \*t = [[Teacher alloc]init]; t.tid = 1; t.name = @"kite"; t.age = 30; NSLog(@"%d,%@,%d",t.tid,t.name,t.age); Hello World Objective C Objective C中的数据类型