【问题标题】:Why tack a protocol of NSObject to a protocol implementation为什么要将 NSObject 的协议附加到协议实现中
【发布时间】:2009-03-25 00:45:29
【问题描述】:

我看到了一些类似于以下的代码:

@protocol MyProtocol <NSObject>
// write some methods.
@end

MyProtocol 符合 NSObject 协议有什么特别的原因吗?如果您执行以下操作,那不是很多余:

id <MyProtocol> foo; // foo here conforms to NSObject AND MyProtocol?

只是好奇这是什么逻辑。

【问题讨论】:

    标签: iphone objective-c cocoa


    【解决方案1】:

    当你声明一个像这样的变量时

     id<MyProtocol> var;
    

    Objective-C 编译器只知道MyProtocol 中的方法,因此如果您尝试在该实例上调用任何NSObject 方法,例如-retain/-release,就会产生警告。因此,Cocoa 定义了一个NSObject 协议,它反映了NSObject 类和实例方法。通过声明MyProtocol 实现NSObject 协议,您可以向编译器提示所有NSObject 方法将由实现MyProtocol 的实例实现。

    为什么这一切都是必要的? Objective-C 允许对象从任何根类继承。在 Cocoa 中,NSObject 是最常见的,但不是唯一的根类。例如,NSProxy 也是一个根类。因此id 类型的实例不一定继承NSObject 的方法。

    【讨论】:

    • 你为什么不能只做“NSObject *variable”?然后你知道它是从 NSObject 派生的,但也符合协议,那么编译器就不会抱怨保留和释放。
    • 实际上,这没关系(就像在使用任何 @protocol(NSObject) 方法之前强制转换为 (NSObject*) 一样。当然,除非实例实际上不是 NSObject。更重要的是,声明实现 NSObject 协议的 MyProtocol 阐明了协议的意图。
    • 如果您的协议不符合 NSObject,我发现最好使用id &lt;MyProtocol,NSObject&gt;。一个原因是id 的动态类型允许您调用编译器可以找到声明的任何方法(没有警告),而不仅仅是从 NSObject 继承或在您的协议中声明的方法。这可能既危险又非常有用,具体取决于您是否做出安全假设。 :-)
    【解决方案2】:

    我很确定您这样做的原因是将 NSObject 成员(比如保留和释放)添加到您的协议中。从技术上讲,您仍然可以发送这些消息,但如果没有它,您会收到编译器警告。

    【讨论】:

    • "从技术上讲,您仍然可以发送这些消息" 如果您不知道它实现了 NSObject 协议,则无法保证对象会理解这些消息。
    • 这个答案足够好
    【解决方案3】:

    当您拥有具有 @optional 方法的协议时,它也非常方便(例如,“现代”Objective-C 2.0 委托经常使用这种技术)如果您不包含 NSObject 协议,您将收到警告你尝试在对象上调用respondsToSelector:

    【讨论】:

    • 不错。这比现在接受的答案更相关,因为 ARC 消除了任何人担心保留/释放的需要。
    【解决方案4】:

    我从未在我的代码中这样做过,但我可以看到它的优势。如果您将参数作为id &lt;SomeProtocol&gt; 传递,如果您想在该对象上调用任何 NSObject 方法,则需要重新转换它。

    【讨论】:

      【解决方案5】:

      如果您使用任何 NSObject 协议方法,例如 retain、release、class、classname,编译器将给您警告,除非您的协议还包含 NSObject 协议。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-08
        • 2015-06-14
        相关资源
        最近更新 更多