非正式协议
Objective-C一个相当普遍的模式就是非正式协议的思想,而这是方法的集合就是一个类有可能不被实现。通常用作托管对象。在Java中,非常普遍用托管来实现接口。这种方式有很多方法,而一些被实现作为没有方法体的方法,而这不是详尽的。
在Objective-C中有两种方式来定义非正式协议。第一种方式通过定义基类上的类别来提供对每个方法的空实现。这意味着每个类将会回应接口中的消息,但只有这样才能显式地实现方法来做任何事。你可以输入一些源文件来使用非正式协议。
@implementation NSObject (MyInformalProtocol)
- (void) handleSomethingFrom:(id) sender {}
@end
- (void) handleSomethingFrom:(id) sender {}
@end
然后你可以轻松的发送一个handleSomethingFrom: 消息给托管对象。注意,你不需要一个@interface部分来划分接口和类别实现。接口是私有的,除了你的类调用这个方法不在需要其它调用,所以不必公开接口。虽然这个技术简单,在很多方面还不是很理想的,因为涉及到用大多数未使用过的cruft来填充父对象委派表(在Apple运行时取决于怎样实现隐藏这会导致轻微的性能衰减)。
另一个选择就是[FS:PAGE]执行运行时测试,如果你给对象发送一个respondsToSelector:消息,你可以找出是否实现了一个命名方法。对于托管,你可以为方法缓存IMP并且在将来直接调用。在你的setDelegate:方法,你将会这样做:
handleMethod = NULL;
if([delegate respondsToSelector:@selector(handleSomethingFrom:))
{
handleMethod = [delegate methodForSelector: @selector(handleSomethingFrom:)];
}
if([delegate respondsToSelector:@selector(handleSomethingFrom:))
{
handleMethod = [delegate methodForSelector: @selector(handleSomethingFrom:)];
}
然后在你是用的地方,你会这么做:
// 等价于[delegate handleSomethingFrom:self];
if (NULL != handleMethod
{
handleMethod(delegate, @selector(handleSomethingFrom:), self);
}
if (NULL != handleMethod
{
handleMethod(delegate, @selector(handleSomethingFrom:), self);
}
Objective-C 2.0 提供了第三个选择,在协议声明中直接使用@optional。这是对空间的极大浪费,因为你需要执行运行时测试来决定一个对象是否遵守一个协议,但事实上从这个协议实现了一个可选择的方法。