似乎protocol
不支持===
运算符,而class
则支持protocol P {
}
class A : P {
}
var a1 = A()
var a2 = A()
var p1:P = a1
var p2:P = a2
a1 === a2 // true
p1 === p2 // error: Type 'P' does not conform to protocol 'AnyObject'
。
struct
我认为这可能是因为符合协议的具体类型也可能是不支持===
运算符的值类型(如p1
)。
我只是想知道如果我确定真正的类型是一个类,我怎么能比较它们的引用,比如这里的p2
和{{1}}?
答案 0 :(得分:37)
首先让我们看一下===
运算符的定义。它不仅仅是对两个实例的值之间的相等性的测试,而是检查两个变量是否指向对象的完全相同的实例(see "Identity Operators" here)。
所以你的示例代码不是很正确:
var a1 = A()
var a2 = A()
var a3 = a2
a1 === a2 // actually false, a1 and a2 were instantiated separately
a2 === a3 // true, because they are the same instance
只有类才能以这种方式进行比较,因为Swift中的所有类都不是值类型*,而且两个值类型的变量可能无法指向同一个实例。
因此,如果您尝试将常规协议与===
进行比较,则Swift没有足够的信息来使用该运算符。您正在比较的实例(p1
和p2
)可能是类实例,也可能是结构实例,而在编译时 Swift可能无法实现告诉它是否可以。
如果您希望能够以这种方式将协议用作类型和与===
进行比较,则您需要声明类协议使用class
作为协议的继承列表中的第一项,如下所示:
protocol P : class {
}
class A : P {
}
现在你可以在没有编译错误的情况下做你正在尝试的事情:
var p1:P = a1
var p2:P = a2
var p3:P = a3
p1 === p2 // false
p2 === p3 // true
*语义上,无论如何。 Swift进行了大量的幕后引用输入,但是强制执行这种值类型的行为,因此出于本讨论的目的,只需使用struct
和enum
进行真正的值类型化。 / p>
答案 1 :(得分:1)
将它放在游乐场和你的路上。
protocol IPositional:class{}
class A:IPositional{}
class B:IPositional{}
let a:IPositional = A()
let b:IPositional = B()
let c:IPositional = a
a === b //false
a === c //true
答案 2 :(得分:0)
使协议符合class
或AnyObject
这意味着仅类将能够遵守该协议,而不是结构。
例如,来自:
protocol P {
}
到( Swift 4版本)
protocol P : AnyObject {
}
或( Swift 3版本)
protocol P : class {
}