OC基础——分类、类本质、SEL



一、分类
1、作用:可以给某一个类扩充一些方法(不修改原来类的代码)。
      格式:
      @interface 类名 (分类名称)
      @end
      @implementation 类名(分类名称)
      @end
2、优点:一个庞大的类可以分模块开发,可以由多人来编写。3
3、分类注意点
       1>分类只是增加方法不能增加成员变量;
       2>分类方法实现中可以访问原来类中的成员变量(主类声明,分类实现);
       3>分类的方法调用,先去分类中找,然后去原来类中找,最后再到父类中找。
       4>分类可以重新实现原来类中的方法,但是会覆盖原来的方法,导致原来的方法无法再使用。
       5> 多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效。
       6>方法调用优先级:分类——>原来类——>父类。

eg:

<span style="font-size:14px;">#import<Foundation/Foundation.h>
@interface NNString (Number)
+(int)numberCountOfString:(NNString *)str;
@end

@implementation NNString(Number)
 +(int)numberCountOfString:(NNString *)str
{
     int count =0;
     for (int i=0;i<str.length;i++)
     {
          if(i>='0'&&i<='9')
          count++
     }
     return count;
}
@end                 

int main()
{ 
  int n = [NNString numberCountOfString:@"abc123";
  NSLog("该字符串中数字个数为:%d",n);
   return 0;
}       </span>

二、类本质:类是由某种类型创造出的一个对像 - > class类型创造出的对象

每个类在内存中只是一个类对象,且类对象由class类型创建。
1> 类本身也是一个对象,是”Class“类型的对象,简称”类对象“。
2> 类名就代表着类对象,每个类只有一个类对象。

 eg:针对Person类的解释
      利用Class类 创建Person类对象,然后利用Person类对象创建Person类型的对象(实例对象)
      Class -> Person类对象 -> 具体的实例对象、
      Class类对象->Person类对象->Person类型对象。
 获取类对象的两种方式:
      Class c = [Person class]; //类方法
或者:
      Person *p = [Person new];
      Class c = [p class]; //对象方法
3>类对象调用类方法
       Class c = [Person class]; 
      person *p = [c new];

+load和+initialize

1、类的加载(+load)
1> 加载顺序:父类—>子类
2> 在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法。
3> +(void)load;//程序一启动的时候,就只调用一次此方法,+load方法存在于NSObject中。

2、类的初始化(+initialize)
1> 加载顺序:父类—>子类
2> 当第一次使用某个类的时候,就会调用一次+initialize方法,用到的时候才会
调用initialize方法,不用的时候不会调用,一个类只会调用一次+initialize方法,而且若调用了子类,父类也会调用一次+initialize方法。
3> +(void)initialize; // 当初始化类时,就会调用此方法,此方法是存在于NSObject。       

三、description方法 
-description:
使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出。
1、- description的作用:帮助输出对象,对象输出到屏幕上是什么内容,需要在description里面说清楚。
2、适用场合:当使用NSLog这个函数,并且使用%@来输出对象的时候,会自动调用description方法。

<span style="font-size:14px;">int main()
{
    Person *p = [[Person alloc]init];
    p.age=20;
    p.name=@"whbsspu";
    NSLog("%@",p);//默认情况下,使用NSLog和%@来输出对象的时候,会调用对象p的-description方法,输出结果为:<类名:内存地址>
    return 0
}</span>

输出结果:


NSLog的工作原理:当我们使用NSLog这个函数,并且使用%@来输出对象的时候:
1> 首先会调用对象的-description方法;
2>  拿到-description的返回值(NSString *)显示到屏幕;
3> -description方法的默认返回值是<类名:内存地址>。          
重写-description方法:
对象输出到屏幕上是什么内容,需要在description里面说清楚,怎么说通过重写-description方法来实现。

-(NSString *)description
{
     return [NSString stringWithFormate:@"sge=%d,name=%d",_age,_name];
}

注意:如果在-description方法中使用NSLog打印self。

+description :使用NSLog和%@输出某个类对象时,会调用类对象+description方法,并拿到返回值进行输出.

<span style="font-family:Microsoft YaHei;font-size:14px;">int main()
{
     Class *p = [Person Class];
     // 1、调用类的description方法;
     // 2、拿到description方法的返回值(NNString *)返回到屏幕上。
     NSLog("%@",p);
}</span>
默认情况下输出类名:

四、SEL(对方法的包装)

类对象中的每个方法都有一个SEL类型的对象。当第一次调用方法时,会将所有方法从上倒下遍历一次, 当找到我们所需要的方法时,就会根据方法的SEL数据,找到方法地址,最终调用方法。
1、 SEL其实是对方法的一种包装,是将方法包装成一个SEL类型的数据,然后根据数据找到对应的方法地址,最后根据地址找到相应的方法,调用方法。即:数据->地址->方法。
所以说发送消息发送的就是SEL类型的数据,就是将方法包装成SEL类型的数据,然后根据SEL类型的数据找到方法地址,根据地址调用方法。
2、 方法的调用过程:1> 把方法包装成SEL类型的数据(每个方法都有一个SEL类型数据);
                                   2> 根据SEL数据找到对应的方法地址;
                                   3> 根据方法地址调用相应的方法。
3、SEL数据调用的两种方式:
1>   通过@select将方法转化为SEL数据
SEL s= @selector(test);//利用selector指令创建出test对应的SEL数据数据。
[p performSelector:s];//使用sel调用test方法
2>  通过函数将字符串转化为SEL数据
NNString *name = @"test";
SEL s1 = NSSelectorFromString(@"test");//把一个字符数据变成一个SEL类型数据。
[p persormSelector:s1];
4、每个方法内部都有一个隐藏的SEL数据:_cmd。_cmd代表当前方法。
1>  eg: [p performSelector:_cmd]; // 将当前方法转化为SEL数据;
2> SEL数据是不能直接打印的,只能转换成字符串打印。
eg:
-(void)test
{
   NNString *str = NSStringFromSelector(_cmd);//_cmd代表test
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值