I'm trying to compare two protocol types using the reference comparison (===
). When I do I get (where Foo
is a protocol):
Binary operator '===' cannot be applied to two 'Foo' operands
I understand why ==
won't work without conforming to Equatable
, but in this case I'm using ===
, which is just an address comparison.
Let's show the problem on declarations:
The ===
operator is declared for AnyObject
.
public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
What exactly is AnyObject
? AnyObject
is a protocol to which all classes automatically conform.
In Swift, there are not only class types, there are also value types, e.g structs and enums. All of them can conform to protocols but structs and enums do not conform to AnyObject
. Since you have Java background, the behavior of value types is similar to primitive types in Java - they are passed by value (copying) and you don't usually get a reference to them.
When you are declaring a protocol, the compiler doesn't know whether it will be adopted by classes or structs.
protocol X {}
struct A: X {}
let x1: X = A()
let x2: X = A()
// PROBLEM - we cannot compare two structs by ===
if x1 === x2 {
}
That means we have to tell the compiler that the protocol can be adopted only by 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 {
}
===
comparator is for comparing references - since structs are value types they pass by value and do not have references. (essentially passing a struct just takes a copy)
Classes are pass by reference - the instance is stored in memory so you are able to use the ===
comparator.
So yes you can compare them, but you need to ensure the protocol is constrained to classes only.
e.g.
//: 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 {
}
would fail to compile
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With