协议不支持" ==="运营商?

时间:2014-08-29 01:20:30

标签: swift

似乎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}}?

3 个答案:

答案 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没有足够的信息来使用该运算符。您正在比较的实例(p1p2)可能是类实例,也可能是结构实例,而在编译时 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进行了大量的幕后引用输入,但是强制执行这种值类型的行为,因此出于本讨论的目的,只需使用structenum进行真正的值类型化。 / 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)

使协议符合classAnyObject 这意味着仅类将能够遵守该协议,而不是结构。

例如,来自:

protocol P {
}

到( Swift 4版本

protocol P : AnyObject {
}

或( Swift 3版本

protocol P : class {
}