如果Protocol方法标记为@required,则在未实现时,为什么编译器会发出警告而不是错误?

时间:2011-12-18 01:59:29

标签: objective-c protocols

假设:

  • 宣布新协议
  • 此协议中的方法标记为@required
  • 类符合协议
  • Class 实现Protocol
  • 中提到的方法

在编译时,有关此方法的信息是已知的:即它是必需的,并且此类和此类可能扩展的任何其他类不会实现它。

为什么在这种情况下编译器会发出警告而不是错误?

5 个答案:

答案 0 :(得分:6)

只有在编译器无法继续时才会发出错误,因为某些内容非常错误。

在Objective-C中调用方法时,方法查找是在运行时完成的,而不是在C ++编译期间完成的。在Objective-C中,“消息”只是发送到对象,类似于obj.executeCommand("Hey, can you execute function <name> for me?")。在C ++中,对象将以obj.<name>()之类的方式直接调用。在Objective-C的情况下,调用executeCommand()方法,该方法存在。在C ++的情况下,函数被调用但它不存在。这些是在编译器级别链接的方法,这意味着它们都成为内存地址而不是名称。 executeCommand变为0x12345678,但仍然使用相同的消息("execute function <name>")。

这可能非常令人困惑,但它与方法以不同语言实现的方式有关。

答案 1 :(得分:2)

如果你对此感到强烈,为什么不打开-Werror

答案 2 :(得分:0)

我不知道真正的答案,但这是一个与之相反的用例。

如果您在类别???

中实现了所有协议方法,该怎么办?

主接口声明采用协议,但协议方法实现属于一个类别。 这是有效的代码,但如果编译器严格,则会显示编译错误!

答案 3 :(得分:0)

Objective-C是一种动态语言。实现的概念与静态语言不同 在大多数情况下,我们大多数人都在@implementation ... @end块中执行代码 但是,如果找不到方法怎么办?然后一个对象有机会动态处理它。

想象一下,你有一个音效播放器的界面:

@protocol FX  
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
@end

实现可以播放文件Beep.mp3,Siren.mp3,Honk.mp3,但不是实现每个方法,而是覆盖 -forwardInvocation:并解析选择器字符串,像这样的伪代码:

NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:@"play"]) {
  NSString filename = fileNameFromSelector(selName);
  [self playSoundFileNamed:filename];
}

这可能看似人为,但是一旦你开始使用该语言的动态功能,你就会开始找到越来越多有意义的地方。我的意思是,从长远来看,这项努力是否有帮助?

在上面的例子中,只需在接口中添加一个-sound *方法名称,然后输入一个适当命名的声音文件。它只是有效。

个人实验的另一个例子:如何以更自然的方式处理核心数据实体。我想做这个: NSArray * people = [Person findAllWithNameLike:@“B%”]; 而不是与谓词混淆,获取请求等 但我不想在代码中定义方法的每个排列。

如果我想构建XML构建器怎么样?我会看一个动态的方法。它很好地服务于Groovy Builders(以Groovy / Grails为例)。

最后一个例子:我有一个特征系统,我可以用方法组的形式定义行为,让我的对象吸收这种行为。因此,虽然编译器没有看到我的对象符合的接口的实现,但实现是使用Objective-C运行时从trait类注入到它中的。我为什么要这样做?我发现许多委托方法都是锅炉板,但同时,每种情况的单个基类都不够灵活。我的'samples'编译并运行:)而不是从代码示例中剪切和粘贴,并且使用该特征在所有项目中反映任何更改。

要真正理解为什么所有这些都可供您使用,值得玩Smalltalk环境(搜索Pharo或Squeak)。这就是Objective-C的根源所在。

最后,要停止这些警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"

@implementation ... @end

#pragma clang diagnostic pop

答案 4 :(得分:0)

因为在设计不良的协议中有时会出现虚假的“必需”方法。 它们应该是可选的,但有人坚持认为它们是“必需的”。 因此,使这成为运行时问题而不是编译错误是非常明智的。