深度解析iPhone内省机制

转载 2012年03月22日 20:14:12

iPhone内省机制是本文要介绍的内容,从评估继承关系、方法实现和协议遵循、对象的比较等方面来详细的学习iPhone内省机制,我们先来看详细内容。

内省(Introspection)是面向对象语言和环境的一个强大特性,Objective-C和Cocoa在这个方面尤其的丰富。内省是对象揭示自己作为一个运行时对象的详细信息的一种能力。这些详细信息包括对象在继承树上的位置,对象是否遵循特定的协议,以及是否可以响应特定的消息。NSObject协议和类定义了很多内省方法,用于查询运行时信息,以便根据对象的特征进行识别。

明智地使用内省可以使面向对象的程序更加高效和强壮。它有助于避免错误地进行消息派发、错误地假设对象相等、以及类似的问题。下面的部分将介绍如何在代码中有效地使用NSObject的内省方法。

评估继承关系

一旦您知道一个对象属于什么类,就可能已经相当了解这个对象了。您可以知道它具有什么能力、哪些属性、以及可以响应哪些消息。即使在内省之后不能了解对象所属的类,也可以知道该对象不能响应特定的消息。

NSObject协议声明了几个方法,用于确定对象在类层次中的位置。这些方法在不同粒度上进行操作,比如class和superclass实例方法分别返回代表类和超类的Class对象。使用这些方法需要将一个Class对象和另一个进行对比。列表2-7给出了一个简单(可能是没有价值)的用法实例。

使用类和超类的方法

  1. // ...
  2. while ( id anObject = [objectEnumerator nextObject] ) {
  3. if ( [self class] == [anObject superclass] ) {
  4. // do something appropriate...
  5. }
  6. }

请注意:有些时候您需要通过class或superclass方法得到正确的类消息接收者。

更加常见的是检查对象类的从属关系,这种情况下您需要向该对象发送isKindOfClass:或isMemberOfClass:消息。前一个方法返回接收者是否为给定类或其继承类的实例,isMemberOfClass:消息则告诉您接收者是否为指定类的实例。isKindOfClass: 方法通常更有用,因为通过它可以知道是否可以向该对象发送一系列消息。考虑列表2-8中的代码片断:

使用isKindOfClass:方法

  1. if ([item isKindOfClass:[NSData class]]) {
  2. const unsigned char *bytes = [item bytes];
  3. unsigned int length = [item length];
  4. // ...
  5. }

确定tem对象是NSData类的继承类的实例之后,代码就知道可以向它发送NSData的bytes和length消息。假定item是NSMutableData类的一个实例,则isKindOfClass:和isMemberOfClass:之间的差别就变得更加明显。如果您调用的是isMemberOfClass:,而不是isKindOfClass:,条件控制块中的代码将永远不会被执行,因为item并不是NSData类的实例,而是其子类NSMutableData的实例。

方法实现和协议遵循

NSObject还有两个功能更加强大的内省方法,即respondsToSelector:和conformsToProtocol:。这两个方法分别告诉您一个对象是否实现特定的方法,以及是否遵循指定的正式协议(即该对象是否采纳了该协议,且实现了该协议的所有方法)。

在代码中,您可以在类似的情况下使用这些方法。通过这些方法,您可以在将消息或消息集合发送给某些潜在的匿名对象之前,确定它们是否可以正确地进行响应。在发送消息之前进行检查可以避免由不能识别的选择器引起的运行时例外。

在实现非正式协议(这种协议是委托技术的基础)时,Application Kit就是在调用委托方法之前检查委托对象是否实现该方法(通过respondsToSelector:方法)。

显示了如何在代码中使用respondsToSelector:方法。

使用respondsToSelector:方法

  1. - (void)doCommandBySelector:(SEL)aSelector {
  2. if ([self respondsToSelector:aSelector]) {
  3. [self performSelector:aSelector withObject:nil];
  4. } else {
  5. [_client doCommandBySelector:aSelector];
  6. }
  7. }

显示如何在代码中使用conformsToProtocol:方法:

使用conformsToProtocol:方法

  1. // ...
  2. if (!([((id)testObject) conformsToProtocol:@protocol(NSMenuItem)])) {
  3. NSLog(@"Custom MenuItem, '%@', not loaded; it must conform to the
  4. 'NSMenuItem' protocol.\n", [testObject class]);
  5. [testObject release];
  6. testObject = nil;
  7. }

对象的比较

hash和isEqual:方法虽然不是严格的内省方法,但是可以发挥类似的作用,是进行对象的识别和比较时不可或缺的运行时工具。它们并不向运行环境查询对象信息,而是依赖于具体类的比较逻辑。

hash和isEqual:方法都在NSObject协议中声明,且彼此关系紧密。实现hash方法必须返回一个整型数,作为哈希表结构中的表地址。两个对象相等(isEqual:方法的判断结果)意味着它们有相同的哈希值。如果您的对象可能被包含在象NSSet这样的集合中,则需要定义hash方法,并确保该方法在两个对象相等的时候返回相同的哈希值。NSObject类中缺省的isEqual:实现只是简单地检查指针是否相等。

isEqual:的使用相当直接,它将消息的接收者和通过参数传入的对象进行比较。对象的比较常常可以在运行时决定应该对对象做些什么。如列表2-11所示,您可以通过isEqual:来确定是否执行某一个动作。在这个例子中,动作是指保存被修改了的预置信息。

使用isEqual:方法

  1. - (void)saveDefaults {
  2. NSDictionary *prefs = [self preferences];
  3. if (![origValues isEqual:prefs])
  4. [Preferences savePreferencesToDefaults:prefs];
  5. }

如果您正在创建子类,则可能需要重载isEqual:方法,以进一步检查对象是否相等。子类可能定义额外的属性,当两个实例被认为相等时,属性的值必须相同。举例来说,假定您创建一个名为MyWidget的NSObject子类,类中包含两个实例变量:name和data。当MyWidget的两个实例被认为是相等时,这些变量必须具有相同的值。列表2-12显示如何在MyWidget类中实现isEqual:方法。

重载isEqual:方法

  1. - (BOOL)isEqual:(id)other {
  2. if (other == self)
  3. return YES;
  4. if (!other || ![other isKindOfClass:[self class]])
  5. return NO;
  6. return [self isEqualToWidget:other];
  7. }
  8. - (BOOL)isEqualToWidget:(MyWidget *)aWidget {
  9. if (self == aWidget)
  10. return YES;
  11. if (![(id)[self name] isEqual:[aWidget name]])
  12. return NO;
  13. if (![[self data] isEqualToData:[aWidget data]])
  14. return NO;
  15. return YES;
  16. }

isEqual:方法首先检查指针的等同性,然后是类的等同性,最后调用对象的比较器进行比较。比较器的名称指示出参与比较的对象的类名称。这种类型的比较器对传入的对象进行强制类型检查,是Cocoa中常见的约定,NSString的isEqualToString:和NSTimeZone的isEqualToTimeZone:就是两个这样的例子。特定类的比较器(在这个例子中是isEqualToWidget:)负责执行name和data变量的等同性。

Cocoa框架的所有isEqualToType:方法中,nil都不是正当的参数,这些方法的实现在接收到nil参数时会抛出例外。然而为了向后兼容,Cocoa框架中的isEqual:方法可以接收nil值,在这种情况下返回NO。

小结:深度解析iPhone内省机制的内容介绍完了,希望本文对你有所帮助!

 

http://mobile.51cto.com/iphone-280494.htm

 

相关文章推荐

深度解析MFC线程及机制.doc

  • 2010年03月09日 18:57
  • 12KB
  • 下载

深度解析iPhone窗口和视图

iPhone窗口和视图是本文要介绍的内容,主要是来了解iphone中的窗口和视图的使用。不多说,一起来看详细内容讲解。 1.程序创建一个UIWindow UIWindow* aWind...

iphone 内省机制

内省内省(Introspection)是面向对象语言和环境的一个强大特性,Objective-C和Cocoa在这个方面尤其的丰富。内省是对象揭示自己作为一个运行时对象的详细信息的一种能力。这些详细信息...

Kafka源码深度解析-序列15 -Log文件结构与flush刷盘机制

Log文件结构在前面我们反复讲topic, partition的概念,本文来分析这些不同topic、不同partition的message,在文件中,是以何种结构存储的。每个topic_partiti...

源码深度解析SpringMvc请求运行机制

本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户...

腾讯反病毒实验室:深度解析AppContainer工作机制

深度解析AppContainer          Win8开始,Windows引入了新的进程隔离机制AppContainer,MetroAPP以及开启EPM的IE Tab进程都运行在AppCont...

Kafka源码深度解析-序列8 -Consumer -Fetcher实现原理与offset确认机制

在进一步介绍之前,我们先通过KafkaConsumer的构造函数,看一下其核心部件: Fetcher, SubscriptionState, ConsumerCoordinator...

Android图片编码机制深度解析(Bitmap,Skia,libJpeg)

问题 工作中遇到了Android中有关图片压缩保存的问题,发现这个问题还挺深,而且网上资料比较有限,因此自己深入研究了一下,算是把这个问题自顶至下全部搞懂了,在此记录。 相关的几个问题如下...

深度解析VC中的消息传递机制

摘要:Windows编程和Dos编程,一个很大的区别就是,Windows编程是事件驱动,消息传递的。所以,要学好Windows编程,必须对消息机制有一个清楚的认识,本文希望能够对消息的传递做一个全面的...

深度解析MySQL查询缓存机制

MySQL查询缓存机制是MySQL数据库中的重要机制之一,下面将为您深入分析MySQL查询缓存机制,供您参考学习之用。MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行相同的sql,服务...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度解析iPhone内省机制
举报原因:
原因补充:

(最多只允许输入30个字)