Objective-C 方法与 Java 或 C++ 方法不同。它们是消息,它们独立于任何类或对象而存在。当您在 Photo.h 中编写(取自CocoaDevCentral)时:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- caption;
- photographer;
@end
你是说这个Photo类有一个标题和一个摄影师对象,它会响应消息caption和photographer. 那是为这两个项目编写代码的旧的 pre-properties 方式。
您将编写代码来Photo.m给出这两条消息的实现,以便 aPhoto可以响应它们。但是没有什么能阻止你发送caption到任何对象。这就像一部关于我们对狗说什么以及它们听到什么的老远方卡通片。任何错误都会在运行时发生。
那么,当您向不知道如何响应的对象发送消息时会发生什么?如果你没有做任何特别的事情,
- 运行时系统将消息打包成一个类型的事物
SEL。
- 它
doesNotRecognizeSelector:使用该选择器将消息发送到对象。
- 该对象继承自
NSObject引发NSInvalidArgumentException.
但是,在此之前有一些机会可以通过覆盖方法进行干预:
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
这使您可以在运行时安装实现。
- (id)forwardingTargetForSelector:(SEL)aSelector
这使您可以指定另一个对象来接受该消息。
- (void)forwardInvocation:(NSInvocation *)anInvocation
这使您可以以任何方式处理消息。
在 Objective-C 获得块之前,有许多库使用转发进行函数式编程。假设您有一个都理解该消息的NSArrayof s。假设您想收集另一个帐户中所有帐户的余额。该库没有循环,而是提供了一个带有消息的类别,您可以编写:AccountbalanceNSArrayNSArraycollect
NSArray *accounts = ...;
NSArray *balances = [[accounts collect] balance];
的结果[accounts collect]没有balance消息的实现;怎么可能? collect由图书馆提供。相反,它有一个forwardInvocation:实现,将balance消息发送给 的所有成员,并从中accounts创建一个新成员。NSArray如今,人们可能会使用积木enumerateObjectsUsingBlock:,但这是一种非常简洁而强大的技术。