`

objective C中的@class, SEL , IMP等灵活机制(五)

 
阅读更多

参考:http://blog.csdn.net/holydancer/article/details/7347399

 

 

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

 

[plain] view plaincopy
  1. @interface NSObject <NSObject> {  
  2.      Class    isa;  
  3.  }  

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

 

 

[plain] view plaincopy
  1. typedefstruct objc_class *Class;  


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

 

 

[plain] view plaincopy
  1. struct objc_class {  
  2.      Class isa;  
  3.        
  4.      Class super_class;  
  5.        
  6.      const char *name;  
  7.        
  8.      long version;  
  9.      long info;  
  10.        
  11.      long instance_size;  
  12.      struct objc_ivar_list *ivars;  
  13.      struct objc_method_list **methodLists;   
  14.        
  15.      struct objc_cache *cache;  
  16.      struct objc_protocol_list *protocols;     
  17.  }  

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

 

Human.h

 

[plain] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface Human : NSObject  
  4. -(void)say;  
  5. @end  


Human.m

 

 

[plain] view plaincopy
  1. #import "Human.h"  
  2.   
  3. @implementation Human  
  4. -(void)say  
  5. {  
  6.     NSLog(@"Human中的say方法");  
  7. }  
  8. @end  


main.h

 

 

[plain] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2. #import "Human.h"  
  3. int main(int argc, const char * argv[])  
  4. {  
  5.   
  6.     @autoreleasepool {  
  7.           
  8.         Class c =NSClassFromString(@"Human");  
  9.         [[c new] say];  
  10.         //以上CLASS类型的c,就相当于Human类。  
  11.     }  
  12.     return 0;  
  13. }  


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

 

 

[plain] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2.   
  3.   
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface Human : NSObject  
  7. -(void)say;  
  8. @end  
  9. @implementation Human  
  10. -(void)say  
  11. {  
  12.     NSLog(@"Human中的say方法");  
  13. }  
  14. @end  
  15. //上面定义了一个human类,里面有一个say方法  
  16. @interface man:NSObject  
  17. {}  
  18. -(void)say; @end  
  19.   
  20. @implementation man  
  21. -(void)say  
  22. {  
  23.     NSLog(@"man中的say方法");  
  24. }  
  25. @end  
  26.   
  27. //在上面定义了一个man类,同样有一个say方法  
  28. int main(int argc, const char * argv[])  
  29. {  
  30.   
  31.     @autoreleasepool {  
  32.           
  33.         Class a =NSClassFromString(@"Human");  
  34.         Class b =NSClassFromString(@"man");  
  35.         //根据方法名say找到该方法的id,将sel与其绑定;  
  36.         SEL sel = NSSelectorFromString(@"say");  
  37.         [[a new] performSelector:sel];  
  38.         [[b new] performSelector:sel];  
  39.           
  40.           
  41.           
  42.     }  
  43.     return 0;  
  44. }  

 

结果如下:

 

[plain] view plaincopy
  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而不是字符串方法名,所以在效率上会高一些。还有一种更终极的方法,直接对应方法的地址,这种方法效率最高,请看代码:

 

[plain] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2.   
  3.   
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface Human : NSObject  
  7. -(void)say;  
  8. @end  
  9. @implementation Human  
  10. -(void)say  
  11. {  
  12.     NSLog(@"Human中的say方法");  
  13. }  
  14. @end  
  15. //上面定义了一个human类,里面有一个say方法  
  16. @interface man:NSObject  
  17. {}  
  18. -(void)say; @end  
  19.   
  20. @implementation man  
  21. -(void)say  
  22. {  
  23.     NSLog(@"man中的say方法");  
  24. }  
  25. @end  
  26.   
  27. //在上面定义了一个man类,同样有一个say方法  
  28. int main(int argc, const char * argv[])  
  29. {  
  30.   
  31.     @autoreleasepool {  
  32.           
  33.         Human *human =[Human new];  
  34.         man *ma=[man new];  
  35.         //根据方法名say找到该方法的id,将sel与其绑定;  
  36.         SEL sel =@selector(say);//也可以这样写:SEL sel=NSSelectorFromString(@"say");  
  37.         IMP imp1 = [human methodForSelector:sel];       
  38.         IMP imp2 = [ma methodForSelector:sel];       
  39.   
  40.         imp1(human,sel);  
  41.         imp2(ma,sel);  
  42.         //因为每个方法都有自己的地址,这种方式直接找到地址区分相同ID的方法,效率最高,但灵活性不如SEL方式。  
  43.           
  44.     }  
  45.     return 0;  
  46. }  

 

输出语句:

[plain] view plaincopy
  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方法,虽然效率最高。好了,今天到此为止。


关键字:objective-c ,objective c , oc ,@class, SEL ,selector ,IMP

 

分享到:
评论

相关推荐

    Class(类类型),Selector(选择器SEL),函数指针(IMP)

    在Objective-C中,Class、Selector(选择器SEL)和函数指针(IMP)是三个非常重要的概念,它们构成了Objective-C动态特性的基础。下面将详细解释这三个概念以及它们之间的关系。 1. Class(类类型): 在Objective...

    深入浅出Object-C之消息[汇编].pdf

    在深入探讨Object-C的消息机制之前,首先我们要理解的是,...通过理解`Class`、`SEL`和`IMP`,我们可以更深入地了解如何在Objective-C中进行方法调用和动态绑定,这对于编写高效和可扩展的Objective-C代码至关重要。

    Objective-C Runtime中的并发内存分配.pdf

    Objective-C Runtime机制是苹果Mac和iOS平台编程中的核心组成部分,它负责支持Objective-C语言运行时的各种特性,其中objc_msgSend函数是Runtime系统中最为关键的一个函数,它处理着所有的消息发送。本文将探讨...

    Objective-C类方法中使用self注意事项

    综上所述,理解`self`在Objective-C类方法中的行为至关重要,正确使用能提高代码的灵活性和可维护性,避免潜在的陷阱。在编写类方法时,应谨慎考虑`self`的使用,确保其符合设计意图,并遵循最佳实践。

    objc runtime 源码 208

    在iOS开发中,Objective-C runtime 是一个至关重要的底层机制,它为Objective-C提供了动态性,使得语言具有灵活性和强大的功能。Objective-C runtime 是一个C语言实现的库,它负责对象的创建、方法调用、类型检查等...

    objective-c的基本知识

    在 Objective-C 中,有几个核心的概念和技术,它们是语言的重要组成部分,对于理解和编写 Objective-C 代码至关重要。 ### 类别(Category) 类别是 Objective-C 的一个独特特性,允许开发者在不创建子类的情况下...

    ios runtime动态添加方法demo

    它是一个C语言库,为Objective-C提供了动态特性的支持,如消息传递、动态类型、方法解析等。在iOS应用开发中,熟练掌握Runtime技术能帮助开发者实现很多高级功能,比如KVO(Key-Value Observing)、Category的扩展、...

    runtime原理与使用

    不同于C语言等静态类型语言,在编译阶段就能确定所有函数的调用细节,Objective-C中的函数调用是一种动态过程,即在程序执行时才能确定具体调用哪个函数。 **关键概念**: 1. **动态调用**:Objective-C中的方法...

    objc4-750-master.zip

    Objective-C runtime是Apple开发的一种运行时系统,它是Objective-C语言的核心组成部分,使得Objective-C具备了动态性与灵活性。在objc4-750-master.zip这个压缩包中,包含了Objective-C runtime的最新版本objc4-750...

    runtime介绍

    在Objective-C中,每个类都对应一个`Class`结构体,它包含了类的基本信息,如类名、父类、实例变量列表、方法列表等。`Class`实际上是一个指向`objc_class`结构的指针。`objc_class`结构中包含了类的继承关系、方法...

    Object-C 疑问解答

    `SEL` 是 Objective-C 中的消息标识符类型,用于唯一标识一个方法。 **5.2 perform: 有什么用途?** `perform:` 方法允许您向对象发送一个指定的选择符(SEL),用于动态调用方法。 **5.3 我如何知道特定 method ...

    iOS 给已有类添加属性

    在iOS开发中,Objective-C是一种主要的编程语言,它提供了强大的动态性,使得开发者可以在运行时修改类的行为。本文将深入探讨如何利用Runtime机制给已有的类添加对象属性和非对象属性。 首先,理解Runtime机制是...

    面试题整理(优化后,需要持续优化)1

    - ABI(Application Binary Interface)是应用程序二进制接口,Objective-C通过引入Class Roaming、Category装载优化等技术,确保在系统升级后仍能保持ABI的稳定性,使得老版本的代码能在新系统上正常运行。...

    一淘网ios入门资料

    - **Objective-C**(简称OC)是一种面向对象的编程语言,它是C语言的超集,并且结合了解释型语言的灵活性与编译型语言的高效执行能力。 - OC支持运行时特性,比如动态绑定和动态消息传递机制,这使得它能够在运行时...

    ExchangeTestApp.zip

    这个技术主要基于Objective-C的动态性,通过修改类的Method Dispatch机制来达到我们的目的。标题"ExchangeTestApp.zip"暗示了这是一个关于方法交换的示例应用,而描述中的"iOS方法交换的各种姿势"则意味着它可能包含...

    runtime10种用法

    Objective-C中的Runtime主要指的是处理消息传递、类和对象管理的一系列底层机制。它提供了强大的功能,使得开发者能够在运行时动态地获取和操作类的信息、对象的状态等。Runtime在iOS开发中有着广泛的应用场景,本文...

    Runtime面试题.pdf

    iOS runtime是Objective-C语言的核心部分,负责对象、类、方法等的动态行为。Runtime面试题通常用于考察面试者对iOS底层机制的理解深度。下面将对给出的内容逐条进行知识点梳理。 1. isa指针 isa指针是Objective-C...

    runtime(获取类属性等信息实例)

    Objective-C runtime是一个底层库,它是Objective-C语言的核心组成部分,它在程序运行时提供了对类、对象、方法、属性等元数据的访问和操作能力。通过runtime,开发者可以实现一些高级特性,如动态类型、消息转发和...

Global site tag (gtag.js) - Google Analytics