gutley
(Gutley)
1
How do I declare an instance variable that conforms to multiple protocols? E.g consider this contrived example:
protocol FlourProvider {
var flour: Flour { get }
}
protocol SugarProvider {
var sugar: Sugar { get }
}
protocol DairyProvider {
var dairy: Dairy { get }
}
protocol HamProvider {
var ham: Ham { get }
}
struct GroceryStore: FlourProvider, SugarProvider, DairyProvider, HamProvider {
...
}
struct Bakery: FlourProvider, SugarProvider, DairyProvider {
...
}
struct CakeMaker {
var ingredientProvider: ????? // Something that provides Flour, Sugar and Dairy
init<T>(ingredientProvider: T) where T: FlourProvider & SugarProvider & DairyProvider {
self.ingredientProvider = ingredientProvider
}
func makeCake() {
mix(ingredientProvider.flour, ingredientProvider.sugar, ingredientProvider.dairy)
}
}
struct PizzaMaker {
var ingredientProvider: ????? // Something provides Flour, Dairy and Ham
init<T>(ingredientProvider: T) where T: FlourProvider & DairyProvider & HamProvider {
self.ingredientProvider = ingredientProvider
}
func makePizza() {
mix(ingredientProvider.flour, ingredientProvider.dairy, ingredientProvider.ham)
}
}
So I'm allowed to init a CakeMaker with either a Bakery or a GroceryStore, but can only init a pizza from a GroceryStore (or anything else able to provide all those ingredients.)
But I can't figure out how to declare the ingredientProvider vars.
atfelix
(Adam Felix)
2
You can use the same protocol composition that you used in the initializer
struct CakeMaker {
var ingredientProvider: FlourProvider & SugarProvider & DairyProvider
}
However, the above won't work if any of your protocols had associated types. In that case you could use generics like so
protocol FlourProvider {
associatedtype Flour
var flour: { get }
}
struct CakeMaker<T: FlourProvider & SugarProvider & DairyProvider> {
var ingredientProvider: T
}
3 Likes