前言:
OC是一门面向对象的语言,因此它也有类、对象、静态\动态方法、成员变量的概念。这讲就来创建第一个OC的类。
一、语法简介
1.类
创建一个类的目的,就是要让其他人都能够使用类提供的外部功能。要创建一个OC类,需要提供两个类信息:一个是类的外部接口(interface),另一个是类的内部实现(Implementation)。
外部接口列出清单,内部实现则是类实现每个功能的具体实现过程。
区分java与C语言还有oc,在java中一个.java就可以描述清楚一个类,而后面两个的画是需要两个文件来描述一个类的。
c语言(oc):
.h: 类的文件,在这里面的方法只是做一个声明,并不进行任何的实现。完整来说就是只是形式一下,内部的具体实现不做。
.cpp(.m): 类的实现文件,用于实现.h中所声明的方法。(类的实现使用关键字@implementation 和 @end)
2.方法
在编程语言中方法存在着类别之分,也就是“静态方法”与“动态方法”,在oc中为了区分这两种方法使用的是"-(动态)"、"+(静态)":
+ :表示类方法(静态方法)【用类名调用的】
- :表示对象方法(动态方法)【用对象名 调用的】
3.成员变量
成员变量的作用域主要有三种:@public 全局都可以访问, @protected 只能在类内部和子类中访问(变量默认类型), @private 只能在类内部访问;
@public
int age;
int lenth;
@protected int benth;
4. 添加方法
在前面知道成员变量是有“作用域”的,部分成员变量外界是不能进行直接访问他的。这就是与面向对象的封装性不符了,为了保证面向对象数据的封装性,可以通过set、get方法,让外界间接访问成员变量。
4.1 在.h文件中声明变量
#import <Foundation/Foundation.h>
@interface Student : NSObject {
int age;
int lenth;
@protected int benth;
}
- (int)getAge;
- (int)getBenth;
- (void)setAge:(int)newAge andNo:(int)newBenth;
@end
1)建议方法名字改成age;OC建议get方法的名字跟成员变量保持一致(如果是在Java中,就应该叫做getAge);-- 正规来讲成员变量是以下划线开始的即_age(这是位了能让成员变量与属性名称区分开);
2)方法的 返回值和 参数类型都需要用小括号()包住;
3)设置set方法,void表示的意思是无返回值类型;在OC方法中, 一个冒号:对应一个参数;而且 冒号:也是方法的一部分;
多个参数之间可以使用andxx连接,也可以不写,使用连接的字符只是为了让方法名比较好念一点,也是为了让冒号前面有点东西;
此时方法名字就变了,如下面方法名字是: setAge:andNo: 而不是setAge andNo;
4)OC方法根据参数进行划分,这样子能够更清晰的表达每个参数的作用;
4.2 在.m文件中实现方法
#import "Student.h"
@implementation Student
//2015/07/14
//设置返回值
- (int)getAge {
NSLog(@"调用了getAge方法");
return age;
}
- (int)getBenth {
NSLog(@"调用了getAge方法");
return benth;
}
//set方法
- (void)setAge:(int)newAge andNo:(int)newBenth {
age = newAge;
benth = newBenth;
}
@end
对于只希望内部使用且不被外界直接访问的方法,则可以直接在类的实现部分.m文件中进行定义。
5. 创建对象
5.1 使用类创建一个对象,在oc中程序的入口点是main函数,所以应该在main.m中演示Student类的使用。
#import <Foundation/Foundation.h>
//由于要用到Student这个类,所以应该包含它的头文件
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//主方法中进行调用
Student *stu = [[Student alloc] init];
[stu setAge:17 andNo:11];
NSLog(@"age is %i and benth is %i", [stu getAge], [stu getBenth]);
}
return 0;
}
5.2 创建对象(与java比较)
1> 在java中使用关键字new来创建对象,比如new Student(), 其实有如下功能:
一是给对象分配存储空间
二是调用Student的构造方法进行初始化
2> 在oc中创建对象其实也是需要做上面的事情的,不过就是语法的差异而已
1) 调用Student的类的静态方法alloc分配空间
Student *stu = [Student alloc];
[1] oc的方法调用是使用中括号[ ],方法调用者写在括号左侧( 如:Student ),方法名写在括号右侧( 如:alloc ),中间留点空格。因此上面调用了Student类的静态方法alloc。
[2] 上面调用的alloc方法会返回分配好内存的Student对象,在等号左边用了一个指向Student类型的指针变量stu 来接收这个对象,注意stu左边的*号。所有OC对象都是用指针变量来接收的,(利用类名定义一个变量时,类名后面一定要带个*号)。
[3] alloc方法是这样声明的:+ (id)alloc;
//它的返回值类型是id,这个id代表任何指针类型,目前可以这么理解:id可以代表任何OC对象,类似于NSObject*。
2) 调用Student对象的构造方法init进行初始化
前面调用alloc方法返回的Student对象stu是不能正常使用的,因为仅仅是分配了内存,并没有进行初始化,接下来调用对象的init方法进行初始化
stu = [stu init];
由于init是动态方法,所以这里使用stu变量来调用,并不是使用类名来调用。init会返回已经初始化完毕的对象,再次赋值给了stu变量。这时候的Student对象stu才能正常使用。
3) 上面的语句结合起来就是
Student *stu = [[Student alloc] init];
6. 销毁对象
在学习java语言时候我们知道java是支持垃圾回收机制的,在oc中是不支持垃圾回收的,也就是说使用完某个对象时候需要我们自己进行销毁。需要调用
对象的release方法释放该对象。
[stu release];
不过会出现一个问题,在xcode新版本是支持自动回收机制的,也就是在xcode里面进行编写的话不需要用户对对象进行垃圾的销毁。 [stu release]; 在xcode中会报错(
'release' is unavailable: not available in automatic reference counting mode..
)这时候用户要是想通过自己手动进行垃圾回收的话,可以在xcode里面进行修改。【Build Settings -- Objectice-c Automatic Reference Counting 设置成no就行】
还有就是release方法在这里调用一次即可,不要觉得多调用多几次,对象就会释放地干净一点,这样容易造成野指针错误。
7.也可以调用静态方法new快速创建一个对象
1 Student *stu = [Student new]; 2 3 [stu release];不过我们还是习惯使用alloc和init来创建对象
8. 访问公共变量和方法
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//主方法中进行调用
Student *stu = [[Student alloc] init];
stu->age = 200;
int age = stu->age;
//stu->benth = 300;(报错)
[stu setAge:17 andNo:11];
NSLog(@"age is %i and benth is %i", [stu getAge], [stu getBenth]);
[stu release];
}
return 0;
}
对变量的访问是通过这种形式的:对象->成员变量;不过只能是公共变量!
感谢(M个J博主)http://www.cnblogs.com/mjios/