OC是一门面向对象的语言,其中自然少不了类。对应C++中的声明和定义,OC的类也分为interface和implementation,并分别以指令
@interface
...
@end
@implementation
...
@end
表述。一般我们会把interface部分放置在.h文件中,而实现部分,则放置在.m文件中。
下面是类Fraction的实例,
Fraction.h头文件:
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
{
int x;
}
// 成员变量
// 省略
//类方法
+(Fraction*) allocF;
+(void) FractionPrint;
//实例方法
-(void) Print;
-(void) setTo:(int) n over:(int) m;
-(double) convertToNum;
-(void) add:(Fraction*) f;
@end
Fraction.m
#import "Fraction.h"
@implementation Fraction
+(Fraction*) allocF
{
return [Fraction alloc];
}
+(void)FractionPrint
{ NSLog(@"This is class function FractionPrint");}
-(void)Print
{
NSLog(@"%i", x);
}
-(void) setTo:(int) n over:(int)m
{
NSLog(@"call setTo");
}
-(double) convertToNum
{
NSLog(@"call convertToNum");
return 1;
}
-(void) add:(Fraction*) f
{
NSLog(@"call add");
}
//存取方法
//暂时省略
@end
上面是OC类的一个实例,对比C++类,有这么几点要注意:
1、OC用函数名称前的+、-号分别表示 类方法 与 实例方法。我们可以简单的对应为C++中的类静态方法与普通成员函数。
同时,对于类方法,对比C++静态函数,OC也有 类似的地方。
(1)OC的类方法只能够访问静态变量或全局变量,而不能够访问类的实例变量。(其原因应该和C++一样,静态方法可以通过类名直接访问,这时候它能访问的仅有静态与全局变量(成员变量要依靠类对象内存空间,所以通过类名直接访问时,成员变量是不存在的)
(2)OC的类方法仅能够通过类名称来调用,而不像C++中静态方法也可以由类对象来调用(但可以通过实例方法来调用静态方法)。
例如对于Fraction类的类方法来说,调用类方法
FractionPrint
#import <Foundation/Foundation.h>
#import "ClassTest.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Fraction* f = [[Fraction allocF] init];
[Fraction FractionPrint]; // 若使用[f FractionPrint]则提示接口没有该方法
}
return 0;
}
2、在OC中,一般的,我们所有的类都继承自NSObjec类,它实现了一些基本的方法,如alloc。
关于OC的几个事实
OC其中有下面几个事实需要注意。
1、OC中类的对象其实是一个C语言中的结构,结构中存储了其对象定义的实例变量及继承来的实例变量。
2、在OC类继承的实例对象中,有一个比较特殊的实例对象isa,通过该对象可以确定对象所属的类。
3、OC类的对象都是分配在堆上的,如其声明所示,
Fraction* f = [[Fraction allocF] init];
OC类对象其实是指向一块结构内存的指针。
4、OC的方法调用最终都会转换为类似下面的C函数调用:
id objc_msgSend ( id self, SEL op, ... );
这里涉及到OC语言的动态语言特性,不同于C\C++语言,OC的所有方法都是在运行时通过向类对象发送消息的方式调用的,不论何种方法,最终都会转换为类似objc_msgSend函数的消息发送。
5、id类型其实是void指针,因此能够接受任意类型的对象返回。同时,由于isa的存在,id对象能够分清它到底是属于哪个类。