Declaring a variable with multiple protocol conformance?

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.

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
Terms of Service

Privacy Policy

Cookie Policy