分类(Category)
分类的作用:在不改变原来类的内容的基础上,为类增加一些方法。
使用注意:
1> 分类只能增加方法,不能增加成员变量
2> 分类方法实现中可以访问原来类中声明的成员变量
3> 分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,导致原方法无法使用。
4> 方法调用优先级:分类(最后参与编译的分类优先)-->原类-->父类 

分类的写法

@interface Person : NSObject
 
  
 
@property NSString *name;
 
 
@property int age;
 
 
+ (void)run;
 
 
@end
 
  
 
@implementation Person
 
 
+ (void)run
 
 
{
 
 
NSLog(@"跑了一圈");
 
 
}
 
 
@end
 
 
// 为Person类添加分类Person1
 
 
@interface Person (Person1)
 
 
- (void)eat;
 
 
@end
 
 
@implementation Person (Person1)
 
 
- (void)eat
 
 
{
 
 
NSLog(@"吃了一顿");
 
 
}
 
 
@end


类的本质

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


类对象的创建

int main()
 
 
{
 
 
Person *p = [[Person alloc] init];
 
 
// 调用分类的eat方法
 
 
[p eat];
 
 
    
 
 
p.name = @"jack";
 
 
p.age = 10;
 
 
// 创建类对象
 
 
Class c = [Person class];
 
 
// 使用类对象创建实例对象,类对象相当于类
 
 
Person *p2 = [[c alloc] init];
 
 
p2.name = @"rose";
 
 
p2.age = 15;
 
 
    
 
 
return 0;
 
 
}


创建了一个Person类的类对象,可以调用Person类的方法。


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

当程序使用某个类时,就会调用当前类的initialize方法

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

先初始化父类,再初始化子类(先调用父类的initialize方法,再调用子类的initialize方法) 


对象的输出

默认情况下,使用NSLog和%@输出对象时, 结果是:<类名:内存地址>

调用对象的description方法,将方法的返回值显示出来。description方法默认的返回值就是 类名:内存地址


@implementation Person (Person1)
 
 
- (void)eat
 
 
{
 
 
NSLog(@"吃了一顿");
 
 
}
 
 
// 重写原类的对象方法description,使其按照格式输出对象成员的值
 
 
-(NSString *)description
 
 
{
 
 
return [NSString stringWithFormat:@"name:%@,age:%d",_name,_age];
 
 
}
 
 
@end




如果想要使用NSLog和%@输出对象的所有属性值时,可以重写description方法来实现。


SEL消息机制

SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址,通过方法地址调用方法。每个方法都有一个对应的SEL类型的数据。


SEL对象的创建

int main()
 
 
{
 
 
Person *p = [[Person alloc] init];
 
 
// 调用分类的eat方法
 
 
[p eat];
 
 
    
 
 
p.name = @"jack";
 
 
p.age = 10;
 
 
// 创建类对象
 
 
Class c = [Person class];
 
 
// 使用类对象创建实例对象,类对象相当于类
 
 
Person *p2 = [[c alloc] init];
 
 
p2.name = @"rose";
 
 
p2.age = 15;
 
 
// 输出对象成员
 
 
NSLog(@"%@",p);
 
 
NSLog(@"%@",p2);
 
 
// 将run方法包装为SEL类型
 
 
SEL s = @selector(run);
 
 
// 调用Person类的run方法
 
 
[c performSelector:s];
 
 
    
 
 
return 0;
 
 
}




NSLog输出

__FILE__ : 源代码文件名

__LINE__ : NSLog代码所在行数

_cmd : 当前方法的SEL,即当前方法的地址。SEL数据无法直接打印,需要先转换为字符串

NSString *str = NSStringFromSelector(_cmd);