博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C中的@class,SEL和IMP等灵活机制
阅读量:6815 次
发布时间:2019-06-26

本文共 3543 字,大约阅读时间需要 11 分钟。

转自holydancer的CSDN专栏,原文地址:


在objective c中,如果细心的话会发现,每个类中都会自动生成一个class 类型的isa


@interface NSObject 
 {     Class    isa; }


isa是什么,class又是什么呢?找到Class的定义我们会发现如下:


typedef struct objc_class *Class;


而objc_class以前的定义又如下,现在据说被封闭了,不知道有没有再作修改,总之方便我们理解就好:


struct objc_class {       Class isa;              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;      }


于是我们就有了点头绪了,isa,is a pointer,是个指针(根据网上的资料,这样理解是最贴近事实的,不管你们信不信,反正我是信了),每个类都有一个class类型的指针isa,继承 自NSObject中,继承关系,方法变量等信息都存放在isa中,isa作为一个隐藏的属性,会自动生成于每个类之中。有了这个前提,也就可以解释为什 么我们可以根据@class来代替任意一个类了,看代码:


//Human.h

#import 
    @interface Human : NSObject  -(void)say;  @end

//Human.m

#import "Human.h"    @implementation Human  -(void)say  {      NSLog(@"Human中的say方法");  }  @end

//main.h

#import 
  #import "Human.h"  int main(int argc, const char * argv[])  {        @autoreleasepool {                    Class c =NSClassFromString(@"Human");          [[c new] say];          //以上CLASS类型的c,就相当于Human类。      }      return 0;  }


class可以灵活的代替别的类,SEL与其类似,不同的是SEL代替的是方法,可以方便的 代替其他方法,class中是因为有isa属性保存有类的信息,而SEL是因为即使是在不同的类中,方法名只要相同,这两个方法的ID就相同,SEL就是 根据这个ID来找到该方法,再根据调用该方法的类的不同来找到唯一的地址。看代码再作解释:


#import 
      #import 
    @interface Human : NSObject  -(void)say;  @end  @implementation Human  -(void)say  {      NSLog(@"Human中的say方法");  }  @end  //上面定义了一个human类,里面有一个say方法  @interface man:NSObject  {}  -(void)say; @end    @implementation man  -(void)say  {      NSLog(@"man中的say方法");  }  @end    //在上面定义了一个man类,同样有一个say方法  int main(int argc, const char * argv[])  {        @autoreleasepool {                    Class a =NSClassFromString(@"Human");          Class b =NSClassFromString(@"man");          //根据方法名say找到该方法的id,将sel与其绑定;          SEL sel = NSSelectorFromString(@"say");          [[a new] performSelector:sel];          [[b new] performSelector:sel];                                    }      return 0;  }

结果如下:

  1. 2012-03-13 10:13:24.900 String[2725:403] Human中的say方法  

  2. 2012-03-13 10:13:24.901 String[2725:403] man中的say方法 

通过以上代码我们会发现,SEL通过方法名绑定后,可以被多个类实例调用,找了些网上的资 料,解释都是说方法名一样的话,ID会一样,地址仍不同,才会实现这样的效果,我们不谈论是否准确,但我个人认为这是目前最合理的解释。这种用法的优势一 方面是灵活性更高,类似于多态,另一方面是,这种用法sel找方法时匹配的是ID而不是字符串方法名,所以在效率上会高一些。还有一种更终极的方法,直接 对应方法的地址,这种方法效率最高,请看代码:


#import 
#import 
@interface Human : NSObject-(void)say;@end@implementation Human-(void)say{    NSLog(@"Human中的say方法");}@end//上面定义了一个human类,里面有一个say方法@interface man:NSObject{}-(void)say; @end@implementation man-(void)say{    NSLog(@"man中的say方法");}@end//在上面定义了一个man类,同样有一个say方法int main(int argc, const char * argv[]){    @autoreleasepool {                Human *human =[Human new];        man *ma=[man new];        //根据方法名say找到该方法的id,将sel与其绑定;        SEL sel =@selector(say);//也可以这样写:SEL sel=NSSelectorFromString(@"say");        IMP imp1 = [human methodForSelector:sel];             IMP imp2 = [ma methodForSelector:sel];             imp1(human,sel);        imp2(ma,sel);        //因为每个方法都有自己的地址,这种方式直接找到地址区分相同ID的方法,效率最高,但灵活性不如SEL方式。            }    return 0;}

输出语句:

  1. 2012-03-13 10:35:21.446 String[3763:403] Human中的say方法  

  2. 2012-03-13 10:35:21.450 String[3763:403] man中的say方法 

总结

class用于代替类,增加灵活性,因为我们不知道什么时候会用到什么类。方法也是如此,所以SEL可以代替方法,每个方法有方法名,ID,地址,相同的方法名。ID也一样,正常情况下我们根据方法名找到方法,用SEL方法可以根据ID找到方法,而用IMP方式可以直接找到地址,但是灵活性不如SEL方法,虽然效率最高。

转载地址:http://tybzl.baihongyu.com/

你可能感兴趣的文章
sa提开放系统下的虚拟新贵Virtualbox权技巧之xp_regwrite替换sethc.exe
查看>>
SpringBoot开发案例之整合Dubbo提供者(一)
查看>>
变态的程序
查看>>
腾讯抄你肿么办 ?
查看>>
java多线程的Fork/Join
查看>>
ftp 服务器的配置
查看>>
JavaScript的浏览器兼容性问题小结。
查看>>
Oracle Hint的用法
查看>>
Postfix邮件系统
查看>>
《编写可读代码的艺术》读书文摘--第一部分 表面层次的改进
查看>>
使用Nodejs创建基本的网站 Microblog--《Node.js开发指南》 3
查看>>
网管工作是否值得做下去?
查看>>
神行者PD10-adb push逃脱ro权限
查看>>
JPA(四)之实体关系一对一
查看>>
如何使用羊驼自动生成缩略图的功能。
查看>>
定制化Azure站点Java运行环境(1)
查看>>
inotify用法简介及结合rsync实现主机间的文件实时同步
查看>>
php 判断手机登陆
查看>>
git 问题
查看>>
Fedora18设置终端快捷键 和 桌面快捷方式
查看>>