13

我正在使用套接字编程。我只是想清除与我从-mobileorchard.com-Chatty下载的代码相关的疑问。在研发期间,我在ChatRoomViewController.m文件中看到了一个函数调用

 [chatRoom broadcastChatMessage:input.text fromUser:[AppConfig getInstance].name];

当我在Room.m 文件中看到,用于执行上述调用;它是

- (void)broadcastChatMessage:(NSString*)message fromUser:(NSString*)name
{
    // Crude way to emulate an "abstract" class
    [self doesNotRecognizeSelector:_cmd];
}

我在谷歌上搜索了“doesNotRecognizeSelector:”,根据Apple的错误处理说明,“只要对象收到无法响应或转发的 aSelector 消息,运行时系统就会调用此方法。” 我的问题是为什么开发人员调用broadcastChatMessage:fromUser:函数,如果它在那里没有使用并处理哪个方法的“未找到选择器”异常?

根据Stackovrflow,它用于创建抽象类,根据这个Question,它是为了避免“不完整的实现”警告。

我仍然不明白为什么在Chatty Code中使用该方法,请帮助我了解使用该方法的原因。

4

2 回答 2

12

这是存在于每个NSObject派生对象上的方法,当在运行时调用中无法识别方法时,它会触发异常路径。例如,如果您尝试将消息发送到被NSString调用的-foo,它将最终到达那里,因为这不是NSString.

在这种情况下,Chatty 类Room是一个从未直接使用的基类。LocalRoomRemoteRoom从中派生,并且这两个类都提供了-broadcastChatMessage:fromUser. 从来没有人调用过那个基类版本,但是为了“完整性”,程序员保证子类必须通过实现方法来覆盖它,然后转身调用它来触发异常。

问题是,这并不是特别惯用的 Objective-C。“抽象”类是来自 C++ 和其他语言的概念;它是仅作为子类的“模式”存在的基类。(在 ObjC 中,这通常是通过@protocol在没有有意义的状态时创建一个正式的状态来完成的,因为那里(大多数情况下)不在这里)。

请注意,调用-doesNotRecognizeSelector:是任意的。这里没有必要避免编译器警告(因为该方法实际上已实现)并且原始作者可以轻松地直接抛出异常,或者什么都不做。

于 2013-04-09T05:39:50.267 回答
4

在我看来,您已经回答了自己的问题。在 Objective-C 中没有创建抽象类的方法,因此最接近的方法是拥有覆盖抛出异常所需的方法。如果你在子类中重写了这个方法,那么doesNotRecognizeSelector:将不再被调用。基本上,这是一种让开发人员承诺在其子类中实现此方法的方法。

此外,正如您所提到的,如果您不将其放入,那么编译器将发出警告,因为头文件中定义的方法不存在任何实现。这将执行与不实现它相同的行为,但编译器会意识到您是故意这样做的。

于 2013-04-09T05:39:54.017 回答