OC---类的深入研究-类的本质

 

 

OC类的本质

类本身也是个对象,是个Class类型的对象,简称类对象

 

类名就代表类对象 也就是代表(类  就是  类对象\类名;  类对象\类名  就是  类)

 每个类只有一个类对象

 

typedef struct objc_class *Class;

 

[对象名  class];  或者[类名 class];   返回类(类对象\类名)

void test()

{

    Person *p1 = [[Person alloc] init];

    

    Person *p2 = [[Person alloc] init];

    

    Class c1 = [p1 class];

    

    Class c2 = [p2 class];

    

    Class c3 = [Person class];

    // c1 == c2 == Person    c1c2c3都代表  类(类对象\类名)---Person

    

    Class c5 = [[[[[[c1 alloc] init] class] alloc] init] class];   // c5还是代表Person这个类的类对象

    

    Class c6 = [[[[[[c3 alloc] init] class] alloc] init] class];   // c6还是代表Person这个类的类对象

    

    NSLog(@"c1==%p, c2==%p, c2==%p, c5==%p, c6==%p",c1, c2, c3, c5, c6);

}

 

调用test函数输出的结果c1==0x100001118, c2==0x100001118, c2==0x100001118, c5==0x100001118, c6==0x100001118

 

+ (void)load方法和+ (void)initialize—类的加载和初始化

在类被加载(只会被加载一次)的时候,系统会自动调用 继承自NSObject类的 + (void)load方法;自己可以在自定义的类.m文件@implementation中重写+ (void)load方法监测类何时被加载

先加载父类,再加载子类(程序运行类就会被加载,类只会被加载一次)

当第一次使用这个类的时候,系统会自动调用一次继承自NSObject类的 + (void)initialize方法

 

总结:

1> 当程序启动的时候,就会加载一次项目中所有的类(和分类),类(和分类)加载完毕后,系统会自动调用一次每个(类和分类) + (void)load方法。只会调用一次。———先加载原始类,再加载分类

2> 当第一次使用这个类的时候,系统会自动调用当前t类的 + (void)initialize方法

3> 先加载父类,再加载子类(先调用父类的+ load方法,再调用子类的+ load方法);

先初始化父类,再初始化子类(先调用父类的+ initialize方法,再调用子类的initialize方法)—如果有分类,就只调用分类的+ initialize方法,不会调用自己的+ initialize方法

4> 如果想在类第一次被使用(初始化)的时候监听一些操作,做一些事情,可以重写该类的+ (void)initialize

 

 

description方法---java的toString()

- description方法

使用NSLog和%@输出某个对象时,会调用对象的- description方法,并拿到返回值输出(系统自定义的返回值是--- <类名:对象的内存地址>)

+ description方法

使用NSLog和%@输出某个类对象时,会调用类对象的+ description方法,并拿到返回值输出(系统自定义的返回值是 ---类名)

description方法相当于java的toString(),一般会重写- description方法输出对象的属性

 

 

SEL(方法的包装类型)

1. 方法的存储位置

1> 每个类的方法列表都存储在类对象中

2> 每个方法都有一个与之对应的SEL类型的数据(对象)

3> 根据一个SEL类型的数据(对象)就可以找到方法的地址,进而调用方法

4> SEL类型的定义

typedef struct objc_selector *SEL;

 

2. SEL对象的建的2中方式

// 创建SEL类型的数据(对象)的2中方式

SEL s = @selector(test);    // 方法名为  test

 

SEL s2 = NSSelectorFromString(@"test:");    // 方法名为 test:

Person *p = [[Person alloc] init];

[p test];

[p performSelector:s];

[p performSelector:NSSelectorFromString(@"test")];

 

[p test:@“aaa"];

[p performSelector:NSSelectorFromString(@"test:") withObject:@“aaa"];

 

[p performSelector:@selector(test:) withObject:@“aaa”];

[p performSelector:s2 withObject:@“aaa”];

 

每个方法内部都有一个内置的SEL类型的数据_cmd 代表着当前方法

- (void)test1

{

    NSString *str = NSStringFromSelector(_cmd);

    NSLog(@"%@", str);    // _cmd == @selector(test1)

}

//  输出结果为   test1

 

总结:

SEL其实是对方法的一种包装,将方法包装为一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2015-04-08 09:56  我是一匹小黑马  阅读(133)  评论(0编辑  收藏  举报