这项声明
protocol SomeProtocol : AnyObject {
}
并且这份声明
protocol SomeProtocol : class {
}
似乎只有类才能符合此协议(即协议的实例是对象的引用),并且没有其他影响。
它们之间有什么区别吗?应该优先选择其中一个吗?如果没有,为什么有两种做同样事情的方式?
我正在使用最新发布的 Xcode 6.3.1。
这是由一位官方Swift开发者(Slava_Pestov)在Swift论坛上回答的。以下是总结:
你应该使用AnyObject
(protocol SomeProtocol: AnyObject
)。
AnyObject
和class
是等价的。没有区别。
class
最终将被弃用。
AnyObject
作为替代使用class
时正在完善。将来后者将取代前者,但目前它们确实存在一些小小的差异。@objc
声明的语义。使用AnyObject
,期望符合协议的类可以是正确或不正确的Objective-C对象,但语言仍然将其视为这样(有时会失去静态调度)。从中可以得出结论,您可以将AnyObject
等协议约束视为请求@objc
成员函数的方法,如STL中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
是AnyObject
的一种更加保守的版本,当您只关心引用语义而不关心动态成员查找或Objective-C桥接时,应该使用它。
AnyObject
,但未提及class
。通过将AnyObject协议添加到协议的继承列表中,可以将协议的采用限制为类类型(而不是结构或枚举)。
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
因此,我建议在编写新代码或新项目时使用AnyObject
而不是class
。除此之外,我没有看到它们之间有任何明显的区别。
如果你在Xcode 9中为class
打开帮助(alt-click),并且在类似于protocol P: class {}
的行中,你将会得到typealias AnyObject
。
因此,在Swift 4中编译的代码将是相同的,无论你将协议约束为class
还是AnyObject
。
尽管如此,也有关于风格和未来选项的问题——未来的Swift版本可能会以某种微妙的方式不同对待class
和AnyObject
,即使现在不是这种情况。
(编辑:Swift 5.4/Xcode 12.5中终于出现了这种情况。)
protocol SomeProtocol : AnyObject { } ; struct Foo : SomeProtocol { }
会导致编译器错误 non-class type 'Foo' cannot conform to class protocol 'SomeProtocol'
。(我感觉实际上没有区别,但我无法证明。) - Martin Rprotocol SomeProtocol: Any
。这让我想知道类限定符的意义所在。我曾经错误地以为它将协议限制为类,而不是类的实例,但文档明确说明了相反的情况。 - Duncan CAnyObject
也完全适用,因为只有对象才能符合该协议,枚举和结构体都无法在期望使用AnyObject
的地方使用。真正的区别在于AnyObject
可以是Swift类或Obj-C对象(或其他符合该协议的内容),但只有Swift类可以符合class
。 - Mecki
AnyObject
和MyClassProtocol
(定义为protocol MyClassProtocol : class {}
)之间的区别是清楚的。我仍然不明白protocol MyObjectProtocol : AnyObject {}
和protocol MyClassProtocol : class {}
之间的区别。 - Martin Rprotocol Protocol : AnyObject {}
与protocol Protocol : class {}
不可互换。 - Martin Rprotocol SomeProtocol : AnyObject { }
和protocol SomeProtocol : class { }
之间根本没有任何区别,但是你声称“...目前,它们确实存在一些细微的差异”。请原谅我的固执,但我仍然看不出你的代码如何展示这种差异。 - Martin Rclass
更为保守 - 我怀疑这是因为它的实现不完整。但它将来也会被淘汰。 - CodaFi