Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol doesn't support the "===" operator?

Tags:

swift

It seems that protocol doesn't support the === operator, while class does.

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' 

I think it could probably caused by the fact that the concrete type that conforms to the protocol could also be a value type (like struct) which doesn't support the === operator. I'm just wondering that if I'm sure the real type is a class, how can I compare the references of them, like the p1 and p2 here?

like image 808
Ken Zhang Avatar asked Aug 29 '14 01:08

Ken Zhang


People also ask

What is use of === in Swift?

The === or identity operator compares the identity of the objects. It checks whether the operands refer to the same object. As you can see, arr1 and arr2 do not refer to the same object, despite the objects being equal.

Can a protocol be Equatable?

The short answer is that we can't. Each conforming type can be Equatable (in fact both our concrete types are) but we don't have a way of checking equality at the level of the protocol since the protocol does not declare any properties.

What is a Swift protocol?

In Swift, a protocol defines a blueprint of methods or properties that can then be adopted by classes (or any other types). We use the protocol keyword to define a protocol. For example, protocol Greet { // blueprint of a property var name: String { get } // blueprint of a method func message() }

What does != Mean in Swift?

I confirm that != is a not equal operator , for e.g: 1 != 2 which really means 1 doesn't equal 2. Hope this helps : )


1 Answers

First let's look at the definition of the === operator. It isn't just a test of equality between the value of two instances, but it checks to see if two variables point to the exact same instance of an object (see "Identity Operators" here).

So your example code isn't quite right:

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 

Only classes can be compared in this way, because everything that isn't a class in Swift is value-typed*, and two value-typed variables can't possibly be pointing to the same instance.

Therefore, if you try to compare a regular protocol with ===, Swift doesn't have enough information to use the operator. The instances you're comparing (p1 and p2) could be class instances or they could be struct instances, and at compile-time Swift can't tell if it's okay.

If you want to be able to use a protocol as a type in this way and compare with ===, you'll need to declare a class-only protocol by using class as the first item in your protocol's inheritance list, like this:

protocol P : class { }  class A : P { } 

Now you can do what you were attempting, without the compiler error:

var p1:P = a1 var p2:P = a2 var p3:P = a3 p1 === p2    // false p2 === p3    // true 

*Semantically, anyway. Swift does a lot of behind-the-scenes reference-typing, but enforces this value-typed behavior, so for the purposes of this discussion just go with struct and enum being truly value-typed.

like image 96
Nate Cook Avatar answered Sep 19 '22 23:09

Nate Cook