协议不支持"==="运算符?

Ken*_*ang 25 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'
Run Code Online (Sandbox Code Playgroud)

我认为这可能是因为符合协议的具体类型也可能是一个struct不支持===运算符的值类型(如).我只是想知道,如果我确定真正的类型是一个类,我怎么能比较它们的引用,比如p1p2这里?

Nat*_*ook 38

首先让我们看一下===运算符的定义.它不仅仅是对两个实例的值之间的相等性的测试,而是检查两个变量是否指向对象的完全相同的实例(请参阅此处的"Identity Operators").

所以你的示例代码不太正确:

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
Run Code Online (Sandbox Code Playgroud)

只能以这种方式比较类,因为Swift中不是类的所有东西都是值类型*,并且两个值类型变量不可能指向同一个实例.

因此,如果您尝试比较常规协议===,Swift没有足够的信息来使用运算符.您正在比较(p1p2)的实例可能是类实例,也可能是结构实例,在编译时, Swift无法判断它是否正常.

如果您希望能够以这种方式将协议用作类型与之进行比较===,则需要使用协议的继承列表中的第一项来声明仅类协议class,如下所示:

protocol P : class {
}

class A : P {
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以执行您尝试的操作,而不会出现编译器错误:

var p1:P = a1
var p2:P = a2
var p3:P = a3
p1 === p2    // false
p2 === p3    // true
Run Code Online (Sandbox Code Playgroud)

*无论如何,语义上.斯威夫特做了很多幕后的基准打字的,但强制执行该值类型的行为,因此这种讨论的目的只有去structenum被真正的值类型.