1. super
这个关键字在OBJ-C的代码里很常见,安装OOP的思想就是,调用父类的方法。
例如下面的代码:
@interface ClassA : NSObject
{
NSString* name;
}
-(void)SetName: (NSString*)name;
@end
@interface ClassB : ClassA
{
NSString* number;
};
-(void)SetNumber:(NSString*)number
-(void)SetNumber:(NSString*)number Name : (NSString)name;
@end
其中我们这里仅实现
-(void)SetNumber:(NSString*)number Name : (NSString)name;
{
[self SetNumber : @"1234"];
[super SetName : "OBJ-C"];
}
这里有两个地方需要注意:
1. [self SetNumber : @"1234"];
上面这行代码是通过id objc_msgSend(id theReceiver, SEL theSelector, ...)这个函数来发送消息,并由self对象来响应。
2. [super SetName : "OBJ-C"];
而这行代码则是通过d objc_msgSendSuper(struct objc_super *super, SEL op, ...)这个函数阿里发现消息。
其中struct objc_super 的结构如下:
struct objc_super {
id receiver; //这个参数存放真正的消息接收者,即是self所指向的对象
Class superClass; //指向父类的类对象
};
他的过程大概为:先从superClass的类对象中查找对应的SEL,这个过程和上面的self对象查找SEL是一致的,如果找到了对应的SEL,在用struct objc_super中的reveiver指向的对象去响应SEL对应的函数。
所以总的来说:super这个他并不是消息的真正接收者,但是查找SEL的过程是从superClass的类对象开始的。
2 self
self这个相对于super要简单很多,一般会把他当作C++中的this指针,其实他与this是有一定的区别的。
区别在于,C++的this指针只在对象方法存在,在静态方法中是不存在的。OBJ-C在对象方法和类方法中都存在self。
在OBJ-C中,存在于两个方法中的self代表的意义是完全不同的。
1. 对象方法中self代表的对象本身,和C++中的this一样。
2. 类方法中的self代表的是类对象,你可以使用[self class]进行操作。例如:你要创建一个实例
+ (id) getInstance
{
id instance = [[[self class] alloc] init];//self是类对象(每一种类存在唯一的类对象和类元,是由系统创建和回收,对用户是透明的)
return [instance autorelease];
}
最后还需要说明一点的是在类方法出现的super,也是类对象,使用方法基本同于self。
总而言之:self在对象方法,和类方法中代表的完全不同的对象(对象本身和类对象)。
3 id
大家都他很熟悉,基本都会说和C/C++的void指针差不多,其实从代码层面来看,确实差不多,但是如果仔细去深挖一些,还是有一些差别的。
在讨论差别之前,先给出几个必要的结构体;
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
id是指向Class指针,同时也是指向struct objc_class指针的指针。
struct objc_class
{
struct objc_class* isa;
struct objc_class* super_class;
const char* name;
long version;
long info;
long instance_size;
struct objc_ivar_list* ivars;
struct objc_method_list** methodLists;
struct objc_cache* cache;
struct objc_protocol_list* protocols;
};
@interface NSObject <NSObject>
{
Class isa;
}
isa:是一个 objc_class 类型的指针
从上面可以看出,每一个从NSObject派生出来的对象的首地址处的四个字节都是一个isa指针,从OBJ-C运行时系统的原理(后面会去分析这个原理)可以知道isa指针在方法调用的过程中起着关键性的作用。其实isa的作用类似于C++的虚表指针。
例如下面这段
ClassA objB = [[classB alloc]init];//ClassB是ClassA的子类
id obj = objB;
[obj classMethod]; //这里classMethod不管是ClassA的方法,还是ClassB的方法,都可以正确的响应,因为isa的作用。
这样写的代码是没有任何问题的(不过效率上慢一点,不过也没有网上说的那么慢,因为大概也就多了一次指针寻址)。但是如果你把C++的void×
来代替id,程序就没办法运行了。其中起着关键性作用的就是isa指针(后续在讨论isa)。这里只是想说明一下,id一个指向id是指向Class指针的指针,不要简单的把它与void×等同起来。