Swift 5.7 introduced primary associated types. While experimenting with this feature, I was wondering if there is still a use case for type erasure types like AnySequence or if primary associated types make those fully obsolete?
For example, if we have the following code:
protocol Car<Fuel> {
associatedtype Fuel
func drive(fuel: Fuel)
}
struct Electricity {}
struct Petrol {}
struct SportsCar: Car {
func drive(fuel: Petrol) { print("️") }
}
struct FamilyCar: Car {
func drive(fuel: Electricity) { print("") }
}
struct WorkCar: Car {
func drive(fuel: Electricity) { print("") }
}
We can now make an array with only electric cars:
let electricCars: [any Car<Electricity>] = [FamilyCar(), WorkCar()]
Previously I would have written something like this:
struct AnyCar<Fuel>: Car {
//Implementation
}
let electricCars: = [AnyCar(FamilyCar()), AnyCar(WorkCar())]
Are there still cases where a custom struct "AnyCar" would make sense?
Thank you!
Although primary associated types do help smooth out many of the edges of using certain existential types, there are still use-cases for manual type erasure using concrete
Any…types.Existential types dynamically dispatch methods which their interface declares down to the underlying value, but critically, they cannot themselves:
A very common example of this is
Equatableconformance. We can update theCarprotocol to adoptEquatableconformance, to indicate thatCars should be able to be equated:However, although you can check for whether two
Carvalues are equal if you know their static types, you cannot check twoany Carvalues for equality:Equatablehas aSelfrequirement whichany Carcannot satisfy; however, you could do this if you wrote your ownAnyCartype:With this wrapper, you can then check two arbitrary
AnyCarvalues for equality:This approach may look familiar to you in the usage of
AnyHashableas a generalized key type for dictionaries which can contain any types of keys. You could not implement the same withany Hashable:As opposed to
AnyCar,AnyHashablehas the benefit of being so prevalent and necessary that the compiler automatically wraps up types inAnyHashableso you don't need to do it yourself, making it largely invisible.