The following code compiled without issue
protocol Animal {
}
var animals = [Animal]()
However, we have a new requirement, where we need to compare array of Animal
protocol Animal {
}
func x(a0: [Animal], a1: [Animal]) -> Bool {
return a0 == a1
}
var animals = [Animal]()
The above code will yield compilation error
protocol ‘Animal’ as a type cannot conform to ‘Equatable’
We tend to fix by
protocol Animal: Equatable {
}
func x(a0: [Animal], a1: [Animal]) -> Bool {
return a0 == a1
}
var animals = [Animal]()
At array declaration line, we are getting error
protocol ‘Animal’ can only be used as a generic constraint because it
has Self or associated type requirements
May I know,
- Why we can have an array of protocol, before the protocol is conforming to Equatable?
- Why we are not allowed to have an array of protocol, once the protocol is conforming to Equatable?
- What are some good ways to fix such error?
3
Answers
Thanks to @Alexander and his pointed video resource - https://youtu.be/_m6DxTEisR8?t=2585
Here's is the good workaround, to overcome the current limitation of Swift's protocol.
Protocol can’t conform to Equatable. The reason is, that it requires Self. Self refers to the concrete(e.g. struct/class) type that conforms to the Equatable. If you want to be able to use protocol instead of concrete type for array, then you need to write compression function yourself:
This part of Swift can be a little confusing, and there are plans to improve it.
When you write something like
a0: [Animal]
, you saying that your function takes an array argument, whose elements are protocol existentials (of theAnimal
protocol).An existential
Animal
is an object that gives its user uniform access to all the requirements (properties, methods, subscripts, initializers, etc.) of theAnimal
protocol, regardless of the concrete type of the underlying conforming object (Cat
,Dog
, etc.).In the new world post SE-0335, you code would have to be spelled like this:
The issue becomes more clear: there’s no guarantee that
a0
anda1
contain animals of the same type. It’s now literally written in the code: they’re arrays of any animal type. Each one can contain animals of any type, and there’s no relationship between the types of the animals ina0
vs ina1
. This is an issue becauseEquatable
is verify specific about its requirements: its==
operator is only applicable to two objects of the same type.To remedy this, you would need to make your function generic, to constain
a0
anda1
to contain objects of some particular type: