Swift - binary operator '===' cannot be applied to two protocols

I am trying to compare two types of protocol using link comparison ( === ). When I get (where Foo is the protocol):

 Binary operator '===' cannot be applied to two 'Foo' operands 

I understand why == will not work without Equatable , but in this case I use === , which is just an address comparison.

+7
swift
source share
3 answers

Let's show a problem over declarations:

The === operator is declared for AnyObject .

 public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool 

What is AnyObject ? AnyObject is a protocol that all classes automatically correspond to.

In Swift, there are not only class types, but also value types, for example, structures and enumerations. All of them can correspond to protocols, but structures and enumerations do not correspond to AnyObject . Since you have a Java background, the behavior of value types is similar to primitive types in Java - they are passed by value (copying), and you usually don't get a reference to them.

When you declare a protocol, the compiler does not know if it will be accepted by classes or structures.

 protocol X {} struct A: X {} let x1: X = A() let x2: X = A() // PROBLEM - we cannot compare two structs by === if x1 === x2 { } 

This means that we must tell the compiler that the protocol can only be accepted in classes:

 protocol X: AnyObject {} 

or

 protocol X: class {} 

Then

 class A: X {} // can be adopted only by classes let x1: X = A() let x2: X = A() // NO problem if x1 === x2 { } 
+5
source share
Comparator

=== is for comparing references — since structs are types of values, they are passed by value and have no references. (essentially, passing the structure just takes a copy)

Classes are passed by reference - the instance is stored in memory, so you can use the comparator === .

So yes, you can compare them, but you need to make sure that the protocol is limited to classes only.

eg.

 //: Playground - noun: a place where people can play protocol Foo: class { } class A: Foo { } class B: Foo { } let a: Foo = A() let b: Foo = A() let c: Foo = B() a === a // true a === b // false a !== c // true b === c // false c === c // true 

Where

 struct B: Foo { } 

failed to compile

+2
source share

with === you can compare two links to some instances, but the protocol type cannot be created!

 protocol P {} class C: P{} let c = C() let p:P = C() c.dynamicType // C.Type p.dynamicType // C.Type 

and

 let p:P = P() // error !!! 

You can tell the compiler that the protocol is a class protocol

 protocol P: class {} class C: P{} struct S: P{} // error: non-class type 'S' cannot conform to class protocol 'P' 

to make sure that the type of value does not match it

see last example

 protocol P: class {} class C: P{} let c = C() let p:P = c p === c // true !! let p1:P = c p === p1 // true !!! 

operator === works

 let c1 = C() let p2:P = c1 p2 === p1 // false !! 
-6
source share

All Articles