您的位置:首页 > 其它

OC类的深入研究

2015-08-19 09:15 453 查看
1、类在创建对象之前也需要加载进空间,也需要占据内存。
2、类只会被加载一次。类也是一个对象,但它的类型是Class类型,就是说类本身也是一个对象,是个Class类型的对象,简称类对象。例如新建一个Person类的对象Person *p=[[Person alloc] init];那么p就是Person类型,而Person是个Class类型的类对象。但平时所说的类就是类对象。

3、由以上得知,创建一个对象的过程是:先由Class类创建出一个类对象,再由类对象创建出一个具体的对象。例如创建一个Person对象时先由Class创建Person类对象,再利用Person类对象创建出Person类型的对象。

4、获取内存中类对象(即对象中isa指针的方法):[对象名 class];

利用对象直接调用从根类继承而来的class对象方法即可返回Class类型的数据。注意:类对象是Class类型的数据,Class类型是指针类型,所以在声明Class类型的类对象时不能再加“*”,因为是个地址,所以在打印时用%p打印地址。

5.获取类对象的几种方法:

(一)、在外部获取

(1)Class c=[对象名 class] ;或Class c=对象名.class;

(2)Class c=[类名 class];或Class c=类名.class;

(二)、在成员方法内获取

无论是在对象方法还是类方法中都可以用以下方式获取(值都一样):

Classc=[self class];或Class c=self.class;

6、获取的类对象的作用:

类名就代表类对象,用类名可以直接调用类方法还可以创建对象。利用类对象同样也可以直接调用类方法,也可以创建对象。

就是说:类对象==类 类对象和类具有同样的功能。类对象的由来:

一个类在内存中只有一个存储空间,我们称这个存储空间为类对象。之所以称为类_对象,是因为它也是由Class这个类创建出来的。

7、类的加载过程:

先加载父类,再加载子类。当程序一启动的时候就会把所有的类都加载了一遍。验证类是否被加载的方法:每个类被加载完时都会调用根类的类方法+(void)load;注意:因为每个类都会被加载一次,仅仅一次,所以每一个类的load类方法都会被执行一次(仅仅一次)。验证时只需要在实现中重写根类的类方法+(void)load即可。

切记:只要程序一启动就会把所有的类给加载一遍,切记是所有的类,不管用到还是没有用到只要在同一个程序都会被加载一遍。

8、监听类的加载过程:

(1)在类被加载的时候调用:+(void)load;这个根类的类方法

(2)在类被加载完毕时再调用:+(void)initialize;这个类方法。

注意:对于+(void)load;这个类方法——>当程序启动的时候就会加载一次项目中所有的类。类加载完毕时就会调用+load方法。

而对于+(void)initialize;这个用于初始化操作的类方法——>当第一次使用这个类的时候,就会被调用一次(仅仅一次),如果从未使用就不会被加载,此处的初始化是指类的初始化。

(3)当所有类加载完毕,使用某个类时会先调用这个类的父类initialize方法初始化这个类从父类继承来的成员,然后再调用自身的initialize方法初始化自己扩展的成员。

(4)分类也会被加载。注意:可以在分类中重写load方法覆盖,但不会覆盖原先类(分类为谁而写的,谁就是原先类)的load方法。分类的load方法最后会被加载。分类中也可以重写initialize类方法进行监听。当所有类和分类都被加载完成时,使用某个类时,如果使用的这个类没有分类或分类中没有重写+initialize方法就会调用这个类的initialize类方法,如果使用的这个类有分类且分类中重写了+initialize方法,就会调用分类的initialize方法而绝对不会再调用父类的initialize类方法,这是因为分类的优先级大于原先类的优先级,用原先类调用任何方法时也与此类似,先从分类找,找不到就依次从原先类、父类中寻找。

9、总结:

(1)当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法。只会调用一次。

(2)当第一次使用某个类时,就会使用当前类的+initialize方法(如果有分类且分类中也重写了+initialize方法的情况下只会调用分类的+initialize方法);

(3)加载时,先加载父类再加载子类(先调用父类的+load方法,再调用子类的+load方法)。初始化的时候,会先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的+initialize方法)。

10、如果想在类的第一次初始化的时候做一些事情,就要为它重写+initialize方法。

代码验证,实例如下:

新建Man.h编辑如下:

<span style="font-size:14px;">//
//  Man.h
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Man : NSObject

@end
</span>


编辑Man.m如下:

<span style="font-size:14px;">//
//  Man.m
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Man.h"

@implementation Man
-(id)init{
if(self=[super init]){
NSLog(@"Man-------—init调用");
}
return self;
}
+(void)load{
NSLog(@"Man-------+load调用");
}
+(void)initialize{
NSLog(@"Man-------+initialize调用");
}
@end
</span>
新建Person.h编辑如下:

<span style="font-size:14px;">//
//  Person.h
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Man.h"

@interface Person : Man
@end
</span>
编辑Person.m如下:

<span style="font-size:14px;">//
//  Person.m
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Person.h"

@implementation Person
-(id)init{
if(self=[super init]){
NSLog(@"Person-------—init调用");
}
return self;
}
+(void)load{
NSLog(@"Person-------+load调用");
}
+(void)initialize{
NSLog(@"Person-------+initialize调用");
}
@end
</span>
新建Student.h如下:

<span style="font-size:14px;">//
//  Student.h
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Person.h"

@interface Student : Person

@end
</span>
编辑Student.m如下:

<span style="font-size:14px;">//
//  Student.m
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Student.h"

@implementation Student
-(id)init{
if(self=[super init]){
NSLog(@"Student-------—init调用");
}
return self;
}
+(void)load{
NSLog(@"Student-------+load调用");
}
+(void)initialize{
NSLog(@"Student-------+initialize调用");
}
@end
</span>

为Student新建分类如下:

编辑Student+MJ.h如下:

//
//  Student+MJ.h
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Student.h"

@interface Student (MJ)

@end
编辑Student+MJ.m如下:

//
//  Student+MJ.m
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "Student+MJ.h"

@implementation Student (MJ)
+(void)load{
NSLog(@"Man分类MJ-------+load调用");//load方法不会覆盖,会将分类、原来类、父类都会一一加载
}
+(void)initialize{
NSLog(@"Man分类MJ-------+initialize调用");//在使用原先类或原先类的子类时,子类和所在的原来类只会被加载一方的initialize方法,因为分类优先级大于原先类,所以只会执行分类的initialize方法。
}
@end


编辑main.m如下:

<span style="font-size:14px;">//
//  main.m
//  类的深入研究
//
//  Created by apple on 15/8/19.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[])
{

@autoreleasepool {
[[Student alloc] init];
[[Man alloc] init];

}
return 0;
}
</span>
运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: