原文地址:http://www.devbean.info/2011/04/from_cpp_to_objc_23/

RTTI (Run-Time Type Information)

RTTI 即运行时类型信息,能够在运行的时候知道需要的类型信息。C++ 有时被认为是一个“假的”面向对象语言。相比 Objective-C,C++ 显得非常静态。这有利于在运行时获得最好的性能。C++ 使用 typeinfo 库提供运行时信息,但这不是安全的,因为这个库依赖于编译器的实现。一般来说,查找对象的类型是一个很少见的请求,因为语言是强类型的,一般在编译时就已经确定其类型了;但是,有时候这种能力对于容器很常用。我们可以使用 dynamic_cast 和 typeid 运算符,但是程序交互则会在一定程度上受限。那么,如何由名字获知这个对象的类型呢?Objective-C 语言可以很容易地实现这种操作。类也是对象,它们继承它们的行为。

class, superclass, isMemberOfClass, isKindOfClass

对象在运行时获取其类型的能力称为内省。内省可以有多种方法实现。

isMemberOfClass: 可以用于回答这种问题:“我是给定类(不包括子类)的实例吗?”,而 isKindOfClass: 则是“我是给定类或其子类的实例吗?”使用这种方法需要一个“假”关键字的 class(注意,不是 @class,@class 是用于前向声明的)。事实上,class 是 NSObject 的一个方法,返回一个 Class 对象。这个对象是元类的一个实例。请注意,nil 值的类是 Nil。

BOOL test = [self isKindOfClass:[Foo class]];
if (test)
    printf("I am an instance of the Foo class\n");

注意,你可以使用 superclass 方法获取其父类。

conformsToProtocol

该方法用于确定一个对象是否和某一协议兼容。我们前面曾经介绍过这个方法。它并不是动态的。编译器仅仅检查每一个显式声明,而不会检查每一个方法。如果一个对象实现了给定协议的所有方法,但并没有显式声明说它实现了该协议,程序运行是正常的,但是 conformsToProtocol: 会返回 NO。

respondsToSelector, instancesRespondToSelector

respondsToSelector: 是一个实例方法,继承自 NSObject。该方法用于检查一个对象是否实现了给定的方法。这里如要使用 @selector。例如:

if ( [self respondsToSelector:@selector(work)] )
{
    printf("I am not lazy.\n");
    [self work];
}

如果要检查一个对象是否实现了给定的方法,而不检查继承的方法,可以使用类方法 instancesRespondToSelector:。例如:

if ([[self class] instancesRespondToSelector:@selector(findWork)])
{
    printf("I can find a job without the help of my mother\n");
}

注意,respondsToSelector: 不能用于仅仅使用了前向声明的类。

强类型和弱类型 id

C++ 使用的是强类型:对象必须符合其类型,否则不能通过编译。在 Objective-C 中,这个限制就灵活得多了。如果一个对象与消息的目标对象不相容,编译器仅仅发出一个警告,而程序则继续运行。这个消息会被丢弃(引发一个异常),除非前面已经转发。如果这就是开发人员期望的,这个警告就是冗余的;在这种情形下,使用弱类型的 id 来替代其真实类型就可以消除警告。事实上,任何对象都是 id 类型的,并且可以处理任何消息。这种弱类型在使用代理的时候是必要的:代理对象不需要知道自己被使用了。例如:

-(void) setAssistant:(id)anObject
{
    [assistant autorelease];
    assistant = [anObject retain];
}
-(void) manageDocument:(Document*)document
{
    if ([assistant respondToSelector:@(manageDocument:)])
        [assistant manageDocument:document];
    else
        printf("Did you fill the blue form ?\n");
}

在 Cocoa 中,这种代理被大量用于图形用户界面的设计中。它可以很方便地把控制权由用户对象移交给工作对象。

运行时操作 Objective-C 类

通过添加头文件 <objc/objc-runtime.h>,我们可以调用很多工具函数,用于在运行时获取类信息、添加方法或实例变量。Objective-C 2.0 又引入了一些新函数,比 Objective-C 1.0 更加灵活(例如使用 class_addMethod(…) 替代 class_addMethods(…)),同时废弃了许多 1.0 的函数。这让我们可以很方便的在运行时修改类。

posted on 2012-06-02 23:08  谭宇(tony)  阅读(152)  评论(0)    收藏  举报