I don\'t think this can be done but I\'ll ask anyway. I have a protocol:
protocol X {}
And a class:
class Y:X {}
The reason why you should think twice about having a protocol conform to Equatable
is that in many cases it just doesn't make sense. Consider this example:
protocol Pet: Equatable {
var age: Int { get }
}
extension Pet {
static func == (lhs: Pet, rhs: Pet) -> Bool {
return lhs.age == rhs.age
}
}
struct Dog: Pet {
let age: Int
let favoriteFood: String
}
struct Cat: Pet {
let age: Int
let favoriteLitter: String
}
let rover: Pet = Dog(age: "1", favoriteFood: "Pizza")
let simba: Pet = Cat(age: "1", favoriteLitter: "Purina")
if rover == simba {
print("Should this be true??")
}
You allude to type checking within the implementation of ==
but the problem is that you have no information about either of the types beyond them being Pet
s and you don't know all the things that might be a Pet
(maybe you will add a Bird
and Rabbit
later). If you really need this, another approach can be modeling how languages like C# implement equality, by doing something like:
protocol IsEqual {
func isEqualTo(_ object: Any) -> Bool
}
protocol Pet: IsEqual {
var age: Int { get }
}
struct Dog: Pet {
let age: Int
let favoriteFood: String
func isEqualTo(_ object: Any) -> Bool {
guard let otherDog = object as? Dog else { return false }
return age == otherDog.age && favoriteFood == otherDog.favoriteFood
}
}
struct Cat: Pet {
let age: Int
let favoriteLitter: String
func isEqualTo(_ object: Any) -> Bool {
guard let otherCat = object as? Cat else { return false }
return age == otherCat.age && favoriteLitter == otherCat.favoriteLitter
}
}
let rover: Pet = Dog(age: "1", favoriteFood: "Pizza")
let simba: Pet = Cat(age: "1", favoriteLitter: "Purina")
if !rover.isEqualTo(simba) {
print("That's more like it.")
}
At which point if you really wanted, you could implement ==
without implementing Equatable
:
static func == (lhs: IsEqual, rhs: IsEqual) -> Bool { return lhs.isEqualTo(rhs) }
One thing you would have to watch out for in this case is inheritance though. Because you could downcast an inheriting type and erase the information that might make isEqualTo
not make logical sense.
The best way to go though is to only implement equality on the class/struct themselves and use another mechanism for type checking.