从AnyObject扩展的协议与仅类协议之间的区别是什么?

时间:2015-05-11 20:13:44

标签: class swift protocols

这个宣言

protocol SomeProtocol : AnyObject {
}

和这个声明

protocol SomeProtocol : class {
}

似乎使得只有类才能符合这个协议(即协议的实例是对象的引用),并且没有其他效果。

它们之间有什么区别吗?一个人应该优先于另一个吗?如果没有,为什么有两种方法可以做同样的事情?

我正在使用最新发布的Xcode 6.3.1。

7 个答案:

答案 0 :(得分:10)

关于答案https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4,此答案已弃用。这些话现在都是一样的。

<强> DEPRECATED

更新:咨询the powers that be后,两个定义假设等同,/*Correct Me If I am wrong*/ 被用作替代,AnyObject是完成了。在未来,后者将消除前者,但目前,它们确实存在一些细微差别。

区别在于class声明的语义。对于@objc,期望符合类可能是也可能不是正确的Objective-C对象,但语言无论如何都将它们视为对待(因为有时你会丢失静态调度)。从中可以看出,你可以对待AnyObject等人。协议约束作为一种询问AnyObject成员函数的方法,如STL中@objc文档中的示例所示:

AnyObject

如果将其更改为import Foundation class C { @objc func getCValue() -> Int { return 42 } } // If x has a method @objc getValue()->Int, call it and // return the result. Otherwise, return nil. func getCValue1(x: AnyObject) -> Int? { if let f: ()->Int = x.getCValue { // <=== return f() } return nil } // A more idiomatic implementation using "optional chaining" func getCValue2(x: AnyObject) -> Int? { return x.getCValue?() // <=== } // An implementation that assumes the required method is present func getCValue3(x: AnyObject) -> Int { // <=== return x.getCValue() // x.getCValue is implicitly unwrapped. // <=== } - 派生协议:

,同样的示例会立即失效
class

所以似乎import Foundation protocol SomeClass : class {} class C : SomeClass { @objc func getCValue() -> Int { return 42 } } // If x has a method @objc getValue()->Int, call it and // return the result. Otherwise, return nil. func getCValue1(x: SomeClass) -> Int? { if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue' return f() } return nil } // A more idiomatic implementation using "optional chaining" func getCValue2(x: SomeClass) -> Int? { return x.getCValue?() // <=== SomeClass has no member 'getCValue' } // An implementation that assumes the required method is present func getCValue3(x: SomeClass) -> Int { // <=== return x.getCValue() // <=== SomeClass has no member 'getCValue' } class的更保守的版本,当你只关心引用语义而不关心动态成员查找或Objective-C桥接时,应该使用它。

答案 1 :(得分:7)

这是由Swift forums上的Swift官方开发人员(Slava_Pestov)回答的。这是摘要:

  • 您应该使用AnyObject protocol SomeProtocol: AnyObject)。

  • AnyObjectclass是等效的。没有区别。

  • class最终将被弃用。

答案 2 :(得分:4)

AnyObject是所有类隐式符合的协议(source)。所以我想说没有区别:你可以使用任何一种来要求类约束。

答案 3 :(得分:4)

Swift programming language guide for protocols仅限类协议部分下。它只提到了AnyObject,但没有提到class

  

通过将AnyObject协议添加到协议的继承列表,可以将协议采用限制为类类型(而不是结构或枚举)。

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

出于这个原因,我建议使用AnyObject而不是class来获取新代码或新项目。除此之外,我认为他们之间没有任何明显的区别。

答案 4 :(得分:2)

从 2021 年开始,Xcode 12.5,Big Sur 操作系统:

苹果不赞成使用 class

改用 AnyObject

快乐编码。

Deprecated

答案 5 :(得分:0)

我之前错过了。 @MartinR应该真的回答这个问题,因为他是纠正我并提供正确信息的人。

真正的区别在于具有类限定符的协议只能应用于类,而不能应用于结构或枚举。

马丁,你为什么不回答,OP可以接受你的回答?

答案 6 :(得分:0)

如果您在class行中的protocol P: class {}的Xcode 9中打开帮助(按住Alt键单击),您将获得typealias AnyObject

因此,无论您将协议约束为class还是AnyObject,编译的代码(在Swift 4中)都是相同的。

也就是说,还有 style future options 的问题 - 未来的Swift版本可能需要处理classAnyObject以某种微妙的方式不同,即使现在情况并非如此。